From d0462be8000f18aa7dc0791d02142f000bb19fbf Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Wed, 22 May 2019 00:58:13 -0700 Subject: Integrate latest changes to tuple definitions --- src/WixToolset.Core/Compiler.cs | 2703 +++++--------------- src/WixToolset.Core/CompilerCore.cs | 150 +- src/WixToolset.Core/Compiler_2.cs | 1919 ++++++-------- src/WixToolset.Core/Compiler_Bundle.cs | 467 ++-- src/WixToolset.Core/Compiler_EmbeddedUI.cs | 12 +- src/WixToolset.Core/Compiler_Module.cs | 79 +- src/WixToolset.Core/Compiler_Patch.cs | 655 +++++ src/WixToolset.Core/Compiler_PatchCreation.cs | 1313 ++++++++++ src/WixToolset.Core/Compiler_UI.cs | 117 +- .../ExtensibilityServices/ParseHelper.cs | 63 +- src/WixToolset.Core/Link/WixGroupingOrdering.cs | 57 +- src/WixToolset.Core/Linker.cs | 29 +- src/WixToolset.Core/Preprocessor.cs | 3 +- src/WixToolset.Core/Resolver.cs | 2 +- src/WixToolset.Core/TransformsFlags.cs | 81 - 15 files changed, 3857 insertions(+), 3793 deletions(-) create mode 100644 src/WixToolset.Core/Compiler_Patch.cs create mode 100644 src/WixToolset.Core/Compiler_PatchCreation.cs delete mode 100644 src/WixToolset.Core/TransformsFlags.cs (limited to 'src/WixToolset.Core') diff --git a/src/WixToolset.Core/Compiler.cs b/src/WixToolset.Core/Compiler.cs index 25cc095b..6be4c9ba 100644 --- a/src/WixToolset.Core/Compiler.cs +++ b/src/WixToolset.Core/Compiler.cs @@ -21,8 +21,11 @@ namespace WixToolset.Core /// internal partial class Compiler : ICompiler { - public const string DefaultComponentIdPlaceholderFormat = "WixComponentIdPlaceholder{0}"; - public const string DefaultComponentIdPlaceholderWixVariableFormat = "!(wix.{0})"; + private const int MinValueOfMaxCabSizeForLargeFileSplitting = 20; // 20 MB + private const int MaxValueOfMaxCabSizeForLargeFileSplitting = 2 * 1024; // 2048 MB (i.e. 2 GB) + + private const string DefaultComponentIdPlaceholderFormat = "WixComponentIdPlaceholder{0}"; + private const string DefaultComponentIdPlaceholderWixVariableFormat = "!(wix.{0})"; // If these are true you know you are building a module or product // but if they are false you cannot not be sure they will not end // up a product or module. Use these flags carefully. @@ -164,6 +167,76 @@ namespace WixToolset.Core return this.Messaging.EncounteredError ? null : target; } + /// + /// Parses a Wix element. + /// + /// Element to parse. + private void ParseWixElement(XElement node) + { + var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + string requiredVersion = null; + + foreach (var attrib in node.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "RequiredVersion": + requiredVersion = this.Core.GetAttributeVersionValue(sourceLineNumbers, attrib); + break; + default: + this.Core.UnexpectedAttribute(node, attrib); + break; + } + } + else + { + this.Core.ParseExtensionAttribute(node, attrib); + } + } + + if (null != requiredVersion) + { + this.Core.VerifyRequiredVersion(sourceLineNumbers, requiredVersion); + } + + foreach (var child in node.Elements()) + { + if (CompilerCore.WixNamespace == child.Name.Namespace) + { + switch (child.Name.LocalName) + { + case "Bundle": + this.ParseBundleElement(child); + break; + case "Fragment": + this.ParseFragmentElement(child); + break; + case "Module": + this.ParseModuleElement(child); + break; + case "PatchCreation": + this.ParsePatchCreationElement(child); + break; + case "Product": + this.ParseProductElement(child); + break; + case "Patch": + this.ParsePatchElement(child); + break; + default: + this.Core.UnexpectedElement(node, child); + break; + } + } + else + { + this.Core.ParseExtensionElement(node, child); + } + } + } + private void ResolveComponentIdPlaceholders(Intermediate target) { if (0 < this.componentIdPlaceholdersResolver.VariableCount) @@ -214,7 +287,7 @@ namespace WixToolset.Core /// Null if the string is null, otherwise returns the lowercase. private static string LowercaseOrNull(string s) { - return (null == s) ? s : s.ToLowerInvariant(); + return s?.ToLowerInvariant(); } /// @@ -227,18 +300,11 @@ namespace WixToolset.Core { if (null != shortName && null != longName && !String.Equals(shortName, longName, StringComparison.OrdinalIgnoreCase)) { - return String.Format(CultureInfo.InvariantCulture, "{0}|{1}", shortName, longName); + return String.Concat(shortName, "|", longName); } else { - if (this.Core.IsValidShortFilename(longName, false)) - { - return longName; - } - else - { - return shortName; - } + return this.Core.IsValidShortFilename(longName, false) ? longName : shortName; } } @@ -246,19 +312,23 @@ namespace WixToolset.Core /// Adds a search property to the active section. /// /// Current source/line number of processing. - /// Property to add to search. + /// Property to add to search. /// Signature for search. - private void AddAppSearch(SourceLineNumber sourceLineNumbers, Identifier property, string signature) + private void AddAppSearch(SourceLineNumber sourceLineNumbers, Identifier propertyId, string signature) { if (!this.Core.EncounteredError) { - if (property.Id != property.Id.ToUpperInvariant()) + if (propertyId.Id != propertyId.Id.ToUpperInvariant()) { - this.Core.Write(ErrorMessages.SearchPropertyNotUppercase(sourceLineNumbers, "Property", "Id", property.Id)); + this.Core.Write(ErrorMessages.SearchPropertyNotUppercase(sourceLineNumbers, "Property", "Id", propertyId.Id)); } - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.AppSearch, property); - row.Set(1, signature); + var tuple = new AppSearchTuple(sourceLineNumbers, propertyId) + { + Signature_ = signature + }; + + this.Core.AddTuple(tuple); } } @@ -266,16 +336,16 @@ namespace WixToolset.Core /// Adds a property to the active section. /// /// Current source/line number of processing. - /// Name of property to add. + /// Identifier of property to add. /// Value of property. /// Flag if property is an admin property. /// Flag if property is a secure property. /// Flag if property is to be hidden. /// Adds the property to a new section. - private void AddProperty(SourceLineNumber sourceLineNumbers, Identifier property, string value, bool admin, bool secure, bool hidden, bool fragment) + private void AddProperty(SourceLineNumber sourceLineNumbers, Identifier propertyId, string value, bool admin, bool secure, bool hidden, bool fragment) { // properties without a valid identifier should not be processed any further - if (null == property || String.IsNullOrEmpty(property.Id)) + if (null == propertyId || String.IsNullOrEmpty(propertyId.Id)) { return; } @@ -290,7 +360,7 @@ namespace WixToolset.Core var group = match.Groups["identifier"]; if (group.Success) { - this.Core.Write(WarningMessages.PropertyValueContainsPropertyReference(sourceLineNumbers, property.Id, group.Value)); + this.Core.Write(WarningMessages.PropertyValueContainsPropertyReference(sourceLineNumbers, propertyId.Id, group.Value)); } } } @@ -302,26 +372,26 @@ namespace WixToolset.Core // Add the row to a separate section if requested. if (fragment) { - var id = String.Concat(this.Core.ActiveSection.Id, ".", property.Id); + var id = String.Concat(this.Core.ActiveSection.Id, ".", propertyId.Id); section = this.Core.CreateSection(id, SectionType.Fragment, this.Core.ActiveSection.Codepage, this.Context.CompilationId); // Reference the property in the active section. - this.Core.CreateSimpleReference(sourceLineNumbers, "Property", property.Id); + this.Core.CreateSimpleReference(sourceLineNumbers, "Property", propertyId.Id); } - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Property, section, property); - // Allow row to exist with no value so that PropertyRefs can be made for *Search elements // the linker will remove these rows before the final output is created. - if (null != value) + var tuple = new PropertyTuple(sourceLineNumbers, propertyId) { - row.Set(1, value); - } + Value = value, + }; + + section.Tuples.Add(tuple); if (admin || hidden || secure) { - this.AddWixPropertyRow(sourceLineNumbers, property, admin, secure, hidden, section); + this.AddWixPropertyRow(sourceLineNumbers, propertyId, admin, secure, hidden, section); } } } @@ -340,10 +410,15 @@ namespace WixToolset.Core this.Core.EnsureTable(sourceLineNumbers, "Property"); // Property table is always required when using WixProperty table. } - var row = (WixPropertyTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixProperty, section, property); - row.Admin = admin; - row.Hidden = hidden; - row.Secure = secure; + var tuple = new WixPropertyTuple(sourceLineNumbers) + { + Property_ = property.Id, + Admin = admin, + Hidden = hidden, + Secure = secure + }; + + section.Tuples.Add(tuple); } /// @@ -375,9 +450,9 @@ namespace WixToolset.Core string localService = null; string serviceParameters = null; string dllSurrogate = null; - var activateAtStorage = YesNoType.NotSet; + bool? activateAtStorage = null; var appIdAdvertise = YesNoType.NotSet; - var runAsInteractiveUser = YesNoType.NotSet; + bool? runAsInteractiveUser = null; string description = null; foreach (var attrib in node.Attributes()) @@ -390,7 +465,7 @@ namespace WixToolset.Core appId = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false); break; case "ActivateAtStorage": - activateAtStorage = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + activateAtStorage = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "Advertise": appIdAdvertise = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); @@ -408,7 +483,7 @@ namespace WixToolset.Core remoteServerName = this.Core.GetAttributeValue(sourceLineNumbers, attrib); break; case "RunAsInteractiveUser": - runAsInteractiveUser = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + runAsInteractiveUser = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "ServiceParameters": serviceParameters = this.Core.GetAttributeValue(sourceLineNumbers, attrib); @@ -473,21 +548,19 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var id = new Identifier(appId, AccessModifier.Public); - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.AppId, id); - row.Set(1, remoteServerName); - row.Set(2, localService); - row.Set(3, serviceParameters); - row.Set(4, dllSurrogate); - if (YesNoType.Yes == activateAtStorage) - { - row.Set(5, 1); - } + var id = new Identifier(AccessModifier.Public, appId); - if (YesNoType.Yes == runAsInteractiveUser) + var tuple = new AppIdTuple(sourceLineNumbers, id) { - row.Set(6, 1); - } + RemoteServerName = remoteServerName, + LocalService = localService, + ServiceParameters = serviceParameters, + DllSurrogate = dllSurrogate, + ActivateAtStorage = activateAtStorage, + RunAsInteractiveUser = runAsInteractiveUser + }; + + this.Core.AddTuple(tuple); } } else if (YesNoType.No == advertise) @@ -521,12 +594,12 @@ namespace WixToolset.Core this.Core.CreateRegistryRow(sourceLineNumbers, RegistryRootType.ClassesRoot, String.Concat("AppID\\", appId), "DllSurrogate", dllSurrogate, componentId); } - if (YesNoType.Yes == activateAtStorage) + if (true == activateAtStorage) { this.Core.CreateRegistryRow(sourceLineNumbers, RegistryRootType.ClassesRoot, String.Concat("AppID\\", appId), "ActivateAtStorage", "Y", componentId); } - if (YesNoType.Yes == runAsInteractiveUser) + if (true == runAsInteractiveUser) { this.Core.CreateRegistryRow(sourceLineNumbers, RegistryRootType.ClassesRoot, String.Concat("AppID\\", appId), "RunAs", "Interactive User", componentId); } @@ -576,10 +649,14 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiAssemblyName); - row.Set(0, componentId); - row.Set(1, id); - row.Set(2, value); + var tuple = new MsiAssemblyNameTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, componentId, id)) + { + Component_ = componentId, + Name = id, + Value = value + }; + + this.Core.AddTuple(tuple); } } @@ -661,12 +738,16 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Binary, id); - row.Set(1, sourceFile); + var tuple = new BinaryTuple(sourceLineNumbers, id) + { + Data = sourceFile + }; + + this.Core.AddTuple(tuple); if (YesNoType.Yes == suppressModularization) { - var wixSuppressModularizationRow = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixSuppressModularization, id); + this.Core.AddTuple(new WixSuppressModularizationTuple(sourceLineNumbers, id)); } } @@ -736,8 +817,10 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Icon, id); - row.Set(1, sourceFile); + this.Core.AddTuple(new IconTuple(sourceLineNumbers, id) + { + Data = sourceFile + }); } return id.Id; @@ -808,7 +891,7 @@ namespace WixToolset.Core private void ParseInstanceElement(XElement node, string propertyId) { var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - string id = null; + Identifier id = null; string productCode = null; string productName = null; string upgradeCode = null; @@ -820,7 +903,7 @@ namespace WixToolset.Core switch (attrib.Name.LocalName) { case "Id": - id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); + id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib); break; case "ProductCode": productCode = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, true); @@ -856,18 +939,15 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixInstanceTransforms); - row.Set(0, id); - row.Set(1, propertyId); - row.Set(2, productCode); - if (null != productName) - { - row.Set(3, productName); - } - if (null != upgradeCode) + var tuple = new WixInstanceTransformsTuple(sourceLineNumbers, id) { - row.Set(4, upgradeCode); - } + PropertyId = propertyId, + ProductCode = productCode, + ProductName = productName, + UpgradeCode = upgradeCode + }; + + this.Core.AddTuple(tuple); } } @@ -928,19 +1008,16 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PublishComponent); - row.Set(0, id); - row.Set(1, qualifier); - row.Set(2, componentId); - row.Set(3, appData); - if (null == feature) + var tuple = new PublishComponentTuple(sourceLineNumbers) { - row.Set(4, Guid.Empty.ToString("B")); - } - else - { - row.Set(4, feature); - } + ComponentId = id, + Qualifier = qualifier, + Component_ = componentId, + AppData = appData, + Feature_ = feature ?? Guid.Empty.ToString("B"), + }; + + this.Core.AddTuple(tuple); } } @@ -1662,7 +1739,7 @@ namespace WixToolset.Core string name = null; string signature = null; RegistryRootType? root = null; - var type = CompilerConstants.IntegerNotSet; + RegLocatorType? type = null; var search64bit = false; foreach (var attrib in node.Attributes()) @@ -1688,13 +1765,13 @@ namespace WixToolset.Core switch (typeValue) { case "directory": - type = 0; + type = RegLocatorType.Directory; break; case "file": - type = 1; + type = RegLocatorType.FileName; break; case "raw": - type = 2; + type = RegLocatorType.Raw; break; case "": break; @@ -1738,7 +1815,7 @@ namespace WixToolset.Core this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Root")); } - if (CompilerConstants.IntegerNotSet == type) + if (!type.HasValue) { this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Type")); } @@ -1776,7 +1853,7 @@ namespace WixToolset.Core } oneChild = true; signature = this.ParseFileSearchElement(child, id.Id, false, CompilerConstants.IntegerNotSet); - id = new Identifier(signature, AccessModifier.Private); // FileSearch signatures override parent signatures + id = new Identifier(AccessModifier.Private, signature); // FileSearch signatures override parent signatures break; case "FileSearchRef": if (oneChild) @@ -1785,7 +1862,7 @@ namespace WixToolset.Core } oneChild = true; var newId = this.ParseSimpleRefElement(child, "Signature"); // FileSearch signatures override parent signatures - id = new Identifier(newId, AccessModifier.Private); + id = new Identifier(AccessModifier.Private, newId); signature = null; break; default: @@ -1799,14 +1876,18 @@ namespace WixToolset.Core } } - if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.RegLocator, id); - row.Set(1, (int)root); - row.Set(2, key); - row.Set(3, name); - row.Set(4, search64bit ? (type | 16) : type); + var tuple = new RegLocatorTuple(sourceLineNumbers, id) + { + Root = root.Value, + Key = key, + Name = name, + Type = type.Value, + Win64 = search64bit + }; + + this.Core.AddTuple(tuple); } return signature; @@ -2017,8 +2098,7 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.CCPSearch); - row.Set(0, signature); + this.Core.AddTuple(new CCPSearchTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, signature))); } } @@ -2044,7 +2124,7 @@ namespace WixToolset.Core var guid = "*"; var componentIdPlaceholder = String.Format(Compiler.DefaultComponentIdPlaceholderFormat, this.componentIdPlaceholdersResolver.VariableCount); // placeholder id for defaulting Component/@Id to keypath id. var componentIdPlaceholderWixVariable = String.Format(Compiler.DefaultComponentIdPlaceholderWixVariableFormat, componentIdPlaceholder); - var id = new Identifier(componentIdPlaceholderWixVariable, AccessModifier.Private); + var id = new Identifier(AccessModifier.Private, componentIdPlaceholderWixVariable); var keyFound = false; string keyPath = null; var shouldAddCreateFolder = false; @@ -2402,9 +2482,13 @@ namespace WixToolset.Core if (shouldAddCreateFolder) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.CreateFolder, new Identifier(AccessModifier.Public, directoryId, id.Id)); - row.Set(0, directoryId); - row.Set(1, id.Id); + var tuple = new CreateFolderTuple(sourceLineNumbers) + { + Directory_ = directoryId, + Component_ = id.Id + }; + + this.Core.AddTuple(tuple); } // check for conditions that exclude this component from using generated guids @@ -2439,7 +2523,7 @@ namespace WixToolset.Core { this.componentIdPlaceholdersResolver.AddVariable(sourceLineNumbers, componentIdPlaceholder, keyPath, false); - id = new Identifier(keyPath, AccessModifier.Private); + id = new Identifier(AccessModifier.Private, keyPath); } else { @@ -2458,7 +2542,6 @@ namespace WixToolset.Core { var tuple = new ComponentTuple(sourceLineNumbers, id) { - Component = id.Id, ComponentId = guid, Directory_ = directoryId, Location = location, @@ -2472,35 +2555,29 @@ namespace WixToolset.Core Shared = shared, Transitive = transitive, UninstallWhenSuperseded = uninstallWhenSuperseded, - Win64 = win64, + Win64 = win64 }; this.Core.AddTuple(tuple); - //var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Component, id); - //row.Set(1, guid); - //row.Set(2, directoryId); - //row.Set(3, bits | keyBits); - //row.Set(4, condition); - //row.Set(5, keyPath); - if (multiInstance) { - //var instanceComponentRow = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixInstanceComponent, id); - - var instanceComponentTuple = new WixInstanceComponentTuple(sourceLineNumbers, id) + this.Core.AddTuple(new WixInstanceComponentTuple(sourceLineNumbers, id) { Component_ = id.Id, - }; - - this.Core.AddTuple(instanceComponentTuple); + }); } if (0 < symbols.Count) { - var symbolRow = (WixDeltaPatchSymbolPathsTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixDeltaPatchSymbolPaths, id); - symbolRow.Type = SymbolPathType.Component; - symbolRow.SymbolPaths = String.Join(";", symbols); + var tupleDelaPatch = new WixDeltaPatchSymbolPathsTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, SymbolPathType.Component, id.Id)) + { + SymbolType = SymbolPathType.Component, + SymbolId = id.Id, + SymbolPaths = String.Join(";", symbols) + }; + + this.Core.AddTuple(tupleDelaPatch); } // Complus @@ -2607,7 +2684,7 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixComponentGroup, id); + this.Core.AddTuple(new WixComponentGroupTuple(sourceLineNumbers, id)); // Add this componentGroup and its parent in WixGroup. this.Core.CreateWixGroupRow(sourceLineNumbers, parentType, parentId, ComplexReferenceChildType.ComponentGroup, id.Id); @@ -2802,7 +2879,7 @@ namespace WixToolset.Core } oneChild = true; signature = this.ParseFileSearchElement(child, id.Id, false, CompilerConstants.IntegerNotSet); - id = new Identifier(signature, AccessModifier.Private); // FileSearch signatures override parent signatures + id = new Identifier(AccessModifier.Private, signature); // FileSearch signatures override parent signatures break; case "FileSearchRef": if (oneChild) @@ -2811,7 +2888,7 @@ namespace WixToolset.Core } oneChild = true; var newId = this.ParseSimpleRefElement(child, "Signature"); // FileSearch signatures override parent signatures - id = new Identifier(newId, AccessModifier.Private); + id = new Identifier(AccessModifier.Private, newId); signature = null; break; default: @@ -2903,9 +2980,13 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.CreateFolder, new Identifier(AccessModifier.Public, directoryId, componentId)); - row.Set(0, directoryId); - row.Set(1, componentId); + var tuple = new CreateFolderTuple(sourceLineNumbers) + { + Directory_ = directoryId, + Component_ = componentId + }; + + this.Core.AddTuple(tuple); } return directoryId; @@ -3026,32 +3107,17 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MoveFile, id); - row.Set(1, componentId); - row.Set(2, sourceName); - row.Set(3, String.IsNullOrEmpty(destinationShortName) && String.IsNullOrEmpty(destinationName) ? null : this.GetMsiFilenameValue(destinationShortName, destinationName)); - if (null != sourceDirectory) + var tuple = new MoveFileTuple(sourceLineNumbers, id) { - row.Set(4, sourceDirectory); - } - else if (null != sourceProperty) - { - row.Set(4, sourceProperty); - } - else - { - row.Set(4, sourceFolder); - } + Component_ = componentId, + SourceName = sourceName, + DestName= String.IsNullOrEmpty(destinationShortName) && String.IsNullOrEmpty(destinationName) ? null : this.GetMsiFilenameValue(destinationShortName, destinationName), + SourceFolder = sourceDirectory ?? sourceProperty, + DestFolder = destinationDirectory ?? destinationProperty, + Delete = delete + }; - if (null != destinationDirectory) - { - row.Set(5, destinationDirectory); - } - else - { - row.Set(5, destinationProperty); - } - row.Set(6, delete ? 1 : 0); + this.Core.AddTuple(tuple); } } else // copy the file @@ -3088,18 +3154,15 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.DuplicateFile, id); - row.Set(1, componentId); - row.Set(2, fileId); - row.Set(3, String.IsNullOrEmpty(destinationShortName) && String.IsNullOrEmpty(destinationName) ? null : this.GetMsiFilenameValue(destinationShortName, destinationName)); - if (null != destinationDirectory) + var tuple = new DuplicateFileTuple(sourceLineNumbers, id) { - row.Set(4, destinationDirectory); - } - else - { - row.Set(4, destinationProperty); - } + Component_ = componentId, + File_ = fileId, + DestName = String.IsNullOrEmpty(destinationShortName) && String.IsNullOrEmpty(destinationName) ? null : this.GetMsiFilenameValue(destinationShortName, destinationName), + DestFolder = destinationDirectory ?? destinationProperty + }; + + this.Core.AddTuple(tuple); } } } @@ -3499,20 +3562,12 @@ namespace WixToolset.Core TSAware = tsAware, Win64 = win64, }; - //var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.CustomAction, id); - //row.Set(1, bits | sourceBits | targetBits); - //row.Set(2, source); - //row.Set(3, target); - //if (0 != extendedBits) - //{ - // row.Set(4, extendedBits); - //} this.Core.AddTuple(tuple); if (YesNoType.Yes == suppressModularization) { - this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixSuppressModularization, id); + this.Core.AddTuple(new WixSuppressModularizationTuple(sourceLineNumbers, id)); } // For deferred CAs that specify HideTarget we should also hide the CA data property for the action. @@ -3618,124 +3673,6 @@ namespace WixToolset.Core } } - /// - /// Parses a PatchFamilyGroup element. - /// - /// Element to parse. - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")] - private void ParsePatchFamilyGroupElement(XElement node, ComplexReferenceParentType parentType, string parentId) - { - var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - Identifier id = null; - - foreach (var attrib in node.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Id": - id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib); - break; - default: - this.Core.UnexpectedAttribute(node, attrib); - break; - } - } - else - { - this.Core.ParseExtensionAttribute(node, attrib); - } - } - - if (null == id) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); - id = Identifier.Invalid; - } - - foreach (var child in node.Elements()) - { - if (CompilerCore.WixNamespace == child.Name.Namespace) - { - switch (child.Name.LocalName) - { - case "PatchFamily": - this.ParsePatchFamilyElement(child, ComplexReferenceParentType.PatchFamilyGroup, id.Id); - break; - case "PatchFamilyRef": - this.ParsePatchFamilyRefElement(child, ComplexReferenceParentType.PatchFamilyGroup, id.Id); - break; - case "PatchFamilyGroupRef": - this.ParsePatchFamilyGroupRefElement(child, ComplexReferenceParentType.PatchFamilyGroup, id.Id); - break; - default: - this.Core.UnexpectedElement(node, child); - break; - } - } - else - { - this.Core.ParseExtensionElement(node, child); - } - } - - if (!this.Core.EncounteredError) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixPatchFamilyGroup, id); - - //Add this PatchFamilyGroup and its parent in WixGroup. - this.Core.CreateWixGroupRow(sourceLineNumbers, parentType, parentId, ComplexReferenceChildType.PatchFamilyGroup, id.Id); - } - } - - /// - /// Parses a PatchFamilyGroup reference element. - /// - /// Element to parse. - /// The type of parent. - /// Identifier of parent element. - private void ParsePatchFamilyGroupRefElement(XElement node, ComplexReferenceParentType parentType, string parentId) - { - Debug.Assert(ComplexReferenceParentType.PatchFamilyGroup == parentType || ComplexReferenceParentType.Patch == parentType); - - var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - string id = null; - - foreach (var attrib in node.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Id": - id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); - this.Core.CreateSimpleReference(sourceLineNumbers, "WixPatchFamilyGroup", id); - break; - default: - this.Core.UnexpectedAttribute(node, attrib); - break; - } - } - else - { - this.Core.ParseExtensionAttribute(node, attrib); - } - } - - if (null == id) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); - } - - this.Core.ParseForExtensionElements(node); - - if (!this.Core.EncounteredError) - { - this.Core.CreateComplexReference(sourceLineNumbers, parentType, parentId, null, ComplexReferenceChildType.PatchFamilyGroup, id, true); - } - } - /// /// Parses an ensure table element. /// @@ -4022,9 +3959,11 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var rowRow = this.Core.CreateRow(childSourceLineNumbers, TupleDefinitionType.WixCustomRow); - rowRow.Set(0, tableId); - rowRow.Set(1, dataValue); + this.Core.AddTuple(new WixCustomRowTuple(childSourceLineNumbers) + { + Table = tableId, + FieldData = dataValue + }); } break; default: @@ -4047,21 +3986,24 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var id = new Identifier(tableId, AccessModifier.Public); - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixCustomTable, id); - row.Set(1, columnCount); - row.Set(2, columnNames); - row.Set(3, columnTypes); - row.Set(4, primaryKeys); - row.Set(5, minValues); - row.Set(6, maxValues); - row.Set(7, keyTables); - row.Set(8, keyColumns); - row.Set(9, categories); - row.Set(10, sets); - row.Set(11, descriptions); - row.Set(12, modularizations); - row.Set(13, bootstrapperApplicationData ? 1 : 0); + var tuple = new WixCustomTableTuple(sourceLineNumbers, new Identifier(AccessModifier.Public, tableId)) + { + ColumnCount = columnCount, + ColumnNames = columnNames, + ColumnTypes = columnTypes, + PrimaryKeys = primaryKeys, + MinValues = minValues, + MaxValues = maxValues, + KeyTables = keyTables, + KeyColumns = keyColumns, + Categories = categories, + Sets = sets, + Descriptions = descriptions, + Modularizations = modularizations, + BootstrapperApplicationData = bootstrapperApplicationData + }; + + this.Core.AddTuple(tuple); } } } @@ -4315,22 +4257,23 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Directory, id); - row.Set(1, parentId); - row.Set(2, defaultDir); - - if (null != componentGuidGenerationSeed) + var tuple = new DirectoryTuple(sourceLineNumbers, id) { - var wixRow = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixDirectory); - wixRow.Set(0, id.Id); - wixRow.Set(1, componentGuidGenerationSeed); - } + Directory_Parent = parentId, + DefaultDir = defaultDir, + ComponentGuidGenerationSeed = componentGuidGenerationSeed + }; + + this.Core.AddTuple(tuple); if (null != symbols) { - var symbolRow = (WixDeltaPatchSymbolPathsTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixDeltaPatchSymbolPaths, id); - symbolRow.Type = SymbolPathType.Directory; - symbolRow.SymbolPaths = symbols; + this.Core.AddTuple(new WixDeltaPatchSymbolPathsTuple(sourceLineNumbers, id) + { + SymbolType = SymbolPathType.Directory, + SymbolId = id.Id, + SymbolPaths = symbols, + }); } } } @@ -4547,14 +4490,19 @@ namespace WixToolset.Core signature = id.Id; } - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.DrLocator, new Identifier(access, rowId, parentSignature, path)); - row.Set(0, rowId); - row.Set(1, parentSignature); - row.Set(2, path); + var tuple = new DrLocatorTuple(sourceLineNumbers) + { + Signature_ = rowId, + Parent = parentSignature, + Path = path, + }; + if (CompilerConstants.IntegerNotSet != depth) { - row.Set(3, depth); + tuple.Depth = depth; } + + this.Core.AddTuple(tuple); } return signature; @@ -5144,7 +5092,7 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixFeatureGroup, id); + this.Core.AddTuple(new WixFeatureGroupTuple(sourceLineNumbers, id)); //Add this FeatureGroup and its parent in WixGroup. this.Core.CreateWixGroupRow(sourceLineNumbers, parentType, parentId, ComplexReferenceChildType.FeatureGroup, id.Id); @@ -5403,8 +5351,13 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Error, new Identifier(AccessModifier.Public, id)); - row.Set(1, Common.GetInnerText(node)); // TODO: * + var tuple = new ErrorTuple(sourceLineNumbers) + { + Error = id, + Message = Common.GetInnerText(node) + }; + + this.Core.AddTuple(tuple); } } @@ -5490,12 +5443,16 @@ namespace WixToolset.Core { if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Extension); - row.Set(0, extension); - row.Set(1, componentId); - row.Set(2, progId); - row.Set(3, mime); - row.Set(4, Guid.Empty.ToString("B")); + var tuple = new ExtensionTuple(sourceLineNumbers, new Identifier(AccessModifier.Public, extension, componentId)) + { + Extension = extension, + Component_ = componentId, + ProgId_ = progId, + MIME_ = mime, + Feature_ = Guid.Empty.ToString("B") + }; + + this.Core.AddTuple(tuple); this.Core.EnsureTable(sourceLineNumbers, "Verb"); } @@ -5560,7 +5517,7 @@ namespace WixToolset.Core string symbols = null; string procArch = null; - var selfRegCost = CompilerConstants.IntegerNotSet; + int? selfRegCost = null; string shortName = null; var source = sourcePath; // assume we'll use the parents as the source for this file var sourceSet = false; @@ -5914,30 +5871,29 @@ namespace WixToolset.Core } } - var fileRow = (FileTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.File, id); - fileRow.Component_ = componentId; - //fileRow.FileName = GetMsiFilenameValue(shortName, name); - fileRow.ShortFileName = shortName; - fileRow.LongFileName = name; - fileRow.FileSize = defaultSize; - if (null != companionFile) - { - fileRow.Version = companionFile; - } - else if (null != defaultVersion) + var tuple = new FileTuple(sourceLineNumbers, id) { - fileRow.Version = defaultVersion; - } - fileRow.Language = defaultLanguage; - fileRow.ReadOnly = readOnly; - fileRow.Checksum = checksum; - fileRow.Compressed = compressed; - fileRow.Hidden = hidden; - fileRow.System = system; - fileRow.Vital = vital; - // the Sequence row is set in the binder + Component_ = componentId, + ShortFileName = shortName, + LongFileName = name, + FileSize = defaultSize, + Version = companionFile ?? defaultVersion, + Language = defaultLanguage, + ReadOnly = readOnly, + Hidden = hidden, + System = system, + Vital = vital, + Checksum = checksum, + Compressed = compressed, + FontTitle = fontTitle, + SelfRegCost = selfRegCost, + BindPath = bindPath, + }; + + this.Core.AddTuple(tuple); - var wixFileRow = (WixFileTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixFile, id); + // TODO: Remove all this. + var wixFileRow = (WixFileTuple)this.Core.CreateTuple(sourceLineNumbers, TupleDefinitionType.WixFile, id); wixFileRow.AssemblyType = assemblyType; wixFileRow.File_AssemblyManifest = assemblyManifest; wixFileRow.File_AssemblyApplication = assemblyApplication; @@ -5951,50 +5907,34 @@ namespace WixToolset.Core // Always create a delta patch row for this file since other elements (like Component and Media) may // want to add symbol paths to it. - var deltaPatchFileRow = (WixDeltaPatchFileTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixDeltaPatchFile, id); - deltaPatchFileRow.RetainLengths = protectLengths; - deltaPatchFileRow.IgnoreOffsets = ignoreOffsets; - deltaPatchFileRow.IgnoreLengths = ignoreLengths; - deltaPatchFileRow.RetainOffsets = protectOffsets; + this.Core.AddTuple(new WixDeltaPatchFileTuple(sourceLineNumbers, id) + { + RetainLengths = protectLengths, + IgnoreOffsets = ignoreOffsets, + IgnoreLengths = ignoreLengths, + RetainOffsets = protectOffsets + }); if (null != symbols) { - var symbolRow = (WixDeltaPatchSymbolPathsTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixDeltaPatchSymbolPaths, id); - symbolRow.Type = SymbolPathType.File; - symbolRow.SymbolPaths = symbols; + this.Core.AddTuple(new WixDeltaPatchSymbolPathsTuple(sourceLineNumbers) + { + SymbolType = SymbolPathType.File, + SymbolId = id.Id, + SymbolPaths = symbols + }); } if (FileAssemblyType.NotAnAssembly != assemblyType) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiAssembly); - row.Set(0, componentId); - row.Set(1, Guid.Empty.ToString("B")); - row.Set(2, assemblyManifest); - row.Set(3, assemblyApplication); - row.Set(4, (FileAssemblyType.DotNetAssembly == assemblyType) ? 0 : 1); - } - - if (null != bindPath) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.BindImage); - row.Set(0, id.Id); - row.Set(1, bindPath); - - // TODO: technically speaking each of the properties in the "bindPath" should be added as references, but how much do we really care about BindImage? - } - - if (CompilerConstants.IntegerNotSet != selfRegCost) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.SelfReg); - row.Set(0, id.Id); - row.Set(1, selfRegCost); - } - - if (null != fontTitle) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Font); - row.Set(0, id.Id); - row.Set(1, fontTitle); + this.Core.AddTuple(new MsiAssemblyTuple(sourceLineNumbers) + { + Component_ = componentId, + Feature_ = Guid.Empty.ToString("B"), + File_Manifest = assemblyManifest, + File_Application = assemblyApplication, + Type = assemblyType + }); } } @@ -6110,7 +6050,7 @@ namespace WixToolset.Core } else // reuse parent signature in the Signature table { - id = new Identifier(parentSignature, AccessModifier.Private); + id = new Identifier(AccessModifier.Private, parentSignature); } } @@ -6138,28 +6078,35 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Signature, id); - row.Set(1, name ?? shortName); - row.Set(2, minVersion); - row.Set(3, maxVersion); + var tuple = new SignatureTuple(sourceLineNumbers, id) + { + FileName = name ?? shortName, + MinVersion = minVersion, + MaxVersion = maxVersion, + Languages = languages + }; if (CompilerConstants.IntegerNotSet != minSize) { - row.Set(4, minSize); + tuple.MinSize = minSize; } + if (CompilerConstants.IntegerNotSet != maxSize) { - row.Set(5, maxSize); + tuple.MaxSize = maxSize; } + if (CompilerConstants.IntegerNotSet != minDate) { - row.Set(6, minDate); + tuple.MinDate = minDate; } + if (CompilerConstants.IntegerNotSet != maxDate) { - row.Set(7, maxDate); + tuple.MaxDate = maxDate; } - row.Set(8, languages); + + this.Core.AddTuple(tuple); // Create a DrLocator row to associate the file with a directory // when a different identifier is specified for the FileSearch. @@ -6169,15 +6116,19 @@ namespace WixToolset.Core { // Creates the DrLocator row for the directory search while // the parent DirectorySearch creates the file locator row. - row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.DrLocator, new Identifier(AccessModifier.Public, parentSignature, id.Id, String.Empty)); - row.Set(0, parentSignature); - row.Set(1, id.Id); + this.Core.AddTuple(new DrLocatorTuple(sourceLineNumbers, new Identifier(AccessModifier.Public, parentSignature, id.Id, String.Empty)) + { + Signature_ = parentSignature, + Parent = id.Id + }); } else { - row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.DrLocator, new Identifier(AccessModifier.Public, id.Id, parentSignature, String.Empty)); - row.Set(0, id.Id); - row.Set(1, parentSignature); + this.Core.AddTuple(new DrLocatorTuple(sourceLineNumbers, new Identifier(AccessModifier.Public, id.Id, parentSignature, String.Empty)) + { + Signature_ = id.Id, + Parent = parentSignature + }); } } } @@ -6193,7 +6144,7 @@ namespace WixToolset.Core private void ParseFragmentElement(XElement node) { var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - string id = null; + Identifier id = null; this.activeName = null; this.activeLanguage = null; @@ -6205,7 +6156,7 @@ namespace WixToolset.Core switch (attrib.Name.LocalName) { case "Id": - id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); + id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib); break; default: this.Core.UnexpectedAttribute(node, attrib); @@ -6220,7 +6171,7 @@ namespace WixToolset.Core // NOTE: Id is not required for Fragments, this is a departure from the normal run of the mill processing. - this.Core.CreateActiveSection(id, SectionType.Fragment, 0, this.Context.CompilationId); + this.Core.CreateActiveSection(id?.Id, SectionType.Fragment, 0, this.Context.CompilationId); var featureDisplay = 0; foreach (var child in node.Elements()) @@ -6232,19 +6183,19 @@ namespace WixToolset.Core case "_locDefinition": break; case "AdminExecuteSequence": - this.ParseSequenceElement(child, child.Name.LocalName); + this.ParseSequenceElement(child, SequenceTable.AdminExecuteSequence); break; case "AdminUISequence": - this.ParseSequenceElement(child, child.Name.LocalName); + this.ParseSequenceElement(child, SequenceTable.AdminUISequence); break; case "AdvertiseExecuteSequence": - this.ParseSequenceElement(child, child.Name.LocalName); + this.ParseSequenceElement(child, SequenceTable.AdvertiseExecuteSequence); break; case "InstallExecuteSequence": - this.ParseSequenceElement(child, child.Name.LocalName); + this.ParseSequenceElement(child, SequenceTable.InstallExecuteSequence); break; case "InstallUISequence": - this.ParseSequenceElement(child, child.Name.LocalName); + this.ParseSequenceElement(child, SequenceTable.InstallUISequence); break; case "AppId": this.ParseAppIdElement(child, null, YesNoType.Yes, null, null, null); @@ -6265,7 +6216,7 @@ namespace WixToolset.Core this.ParseComponentElement(child, ComplexReferenceParentType.Unknown, null, null, CompilerConstants.IntegerNotSet, null, null); break; case "ComponentGroup": - this.ParseComponentGroupElement(child, ComplexReferenceParentType.Unknown, id); + this.ParseComponentGroupElement(child, ComplexReferenceParentType.Unknown, id?.Id); break; case "Condition": this.ParseConditionElement(child, node.Name.LocalName, null, null); @@ -6301,7 +6252,7 @@ namespace WixToolset.Core this.ParseFeatureElement(child, ComplexReferenceParentType.Unknown, null, ref featureDisplay); break; case "FeatureGroup": - this.ParseFeatureGroupElement(child, ComplexReferenceParentType.Unknown, id); + this.ParseFeatureGroupElement(child, ComplexReferenceParentType.Unknown, id.Id); break; case "FeatureRef": this.ParseFeatureRefElement(child, ComplexReferenceParentType.Unknown, null); @@ -6326,13 +6277,13 @@ namespace WixToolset.Core this.ParseCertificatesElement(child); break; case "PatchFamily": - this.ParsePatchFamilyElement(child, ComplexReferenceParentType.Unknown, id); + this.ParsePatchFamilyElement(child, ComplexReferenceParentType.Unknown, id.Id); break; case "PatchFamilyGroup": - this.ParsePatchFamilyGroupElement(child, ComplexReferenceParentType.Unknown, id); + this.ParsePatchFamilyGroupElement(child, ComplexReferenceParentType.Unknown, id.Id); break; case "PatchFamilyGroupRef": - this.ParsePatchFamilyGroupRefElement(child, ComplexReferenceParentType.Unknown, id); + this.ParsePatchFamilyGroupRefElement(child, ComplexReferenceParentType.Unknown, id.Id); break; case "PayloadGroup": this.ParsePayloadGroupElement(child, ComplexReferenceParentType.Unknown, null); @@ -6384,8 +6335,7 @@ namespace WixToolset.Core if (!this.Core.EncounteredError && null != id) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixFragment); - row.Set(0, id); + this.Core.AddTuple(new WixFragmentTuple(sourceLineNumbers, id)); } } @@ -6498,11 +6448,13 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ControlCondition); - row.Set(0, dialog); - row.Set(1, id); - row.Set(2, action); - row.Set(3, condition); + this.Core.AddTuple(new ControlConditionTuple(sourceLineNumbers) + { + Dialog_ = dialog, + Control_ = id, + Action = action, + Condition = condition, + }); } break; case "Feature": @@ -6514,10 +6466,12 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Condition); - row.Set(0, id); - row.Set(1, level); - row.Set(2, condition); + this.Core.AddTuple(new ConditionTuple(sourceLineNumbers) + { + Feature_ = id, + Level = level, + Condition = condition + }); } break; case "Fragment": @@ -6529,9 +6483,11 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.LaunchCondition); - row.Set(0, condition); - row.Set(1, message); + this.Core.AddTuple(new LaunchConditionTuple(sourceLineNumbers) + { + Condition = condition, + Description = message + }); } break; } @@ -6836,7 +6792,7 @@ namespace WixToolset.Core } oneChild = true; signature = this.ParseFileSearchElement(child, id.Id, false, CompilerConstants.IntegerNotSet); - id = new Identifier(signature, AccessModifier.Private); // FileSearch signatures override parent signatures + id = new Identifier(AccessModifier.Private, signature); // FileSearch signatures override parent signatures break; case "FileSearchRef": if (oneChild) @@ -6845,7 +6801,7 @@ namespace WixToolset.Core } oneChild = true; var newId = this.ParseSimpleRefElement(child, "Signature"); // FileSearch signatures override parent signatures - id = new Identifier(newId, AccessModifier.Private); + id = new Identifier(AccessModifier.Private, newId); signature = null; break; default: @@ -6861,15 +6817,20 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.IniLocator, id); - row.Set(1, this.GetMsiFilenameValue(shortName, name)); - row.Set(2, section); - row.Set(3, key); + var tuple = new IniLocatorTuple(sourceLineNumbers, id) + { + FileName = this.GetMsiFilenameValue(shortName, name), + Section = section, + Key = key, + Type = type + }; + if (CompilerConstants.IntegerNotSet != field) { - row.Set(4, field); + tuple.Field = field; } - row.Set(5, type); + + this.Core.AddTuple(tuple); } return signature; @@ -6915,9 +6876,11 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.IsolatedComponent); - row.Set(0, shared); - row.Set(1, componentId); + this.Core.AddTuple(new IsolatedComponentTuple(sourceLineNumbers) + { + Component_Shared = shared, + Component_Application = componentId + }); } } @@ -6953,9 +6916,9 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, "PatchCertificates" == node.Name.LocalName ? TupleDefinitionType.MsiPatchCertificate : TupleDefinitionType.MsiPackageCertificate); - row.Set(0, name); - row.Set(1, name); + var tuple = this.Core.CreateTuple(sourceLineNumbers, "PatchCertificates" == node.Name.LocalName ? TupleDefinitionType.MsiPatchCertificate : TupleDefinitionType.MsiPackageCertificate); + tuple.Set(0, name); + tuple.Set(1, name); } break; default: @@ -7026,8 +6989,10 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiDigitalCertificate, id); - row.Set(1, sourceFile); + this.Core.AddTuple(new MsiDigitalCertificateTuple(sourceLineNumbers, id) + { + CertData = sourceFile + }); } return id.Id; @@ -7097,11 +7062,13 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiDigitalSignature); - row.Set(0, "Media"); - row.Set(1, diskId); - row.Set(2, certificateId); - row.Set(3, sourceFile); + this.Core.AddTuple(new MsiDigitalSignatureTuple(sourceLineNumbers, new Identifier(AccessModifier.Public, "Media", diskId)) + { + Table = "Media", + SignObject = diskId, + DigitalCertificate_ = certificateId, + Hash = sourceFile + }); } } @@ -7242,7 +7209,7 @@ namespace WixToolset.Core this.Core.AddTuple(tuple); // Ensure the action property is secure. - this.AddWixPropertyRow(sourceLineNumbers, new Identifier(Common.UpgradeDetectedProperty, AccessModifier.Public), false, true, false); + this.AddWixPropertyRow(sourceLineNumbers, new Identifier(AccessModifier.Public, Common.UpgradeDetectedProperty), false, true, false); // Add launch condition that blocks upgrades if (blockUpgrades) @@ -7273,7 +7240,7 @@ namespace WixToolset.Core this.Core.AddTuple(upgradeTuple); // Ensure the action property is secure. - this.AddWixPropertyRow(sourceLineNumbers, new Identifier(Common.DowngradeDetectedProperty, AccessModifier.Public), false, true, false); + this.AddWixPropertyRow(sourceLineNumbers, new Identifier(AccessModifier.Public, Common.DowngradeDetectedProperty), false, true, false); var conditionTuple = new LaunchConditionTuple(sourceLineNumbers) { @@ -7479,29 +7446,27 @@ namespace WixToolset.Core // add the row to the section if (!this.Core.EncounteredError) { - var mediaRow = (MediaTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Media, new Identifier(id, AccessModifier.Public)); - mediaRow.LastSequence = 0; // this is set in the binder - mediaRow.DiskPrompt = diskPrompt; - mediaRow.Cabinet = cabinet; - mediaRow.VolumeLabel = volumeLabel; - mediaRow.Source = source; - - // the Source column is only set when creating a patch - - if (null != compressionLevel || null != layout) + var tuple = new MediaTuple(sourceLineNumbers, new Identifier(AccessModifier.Public, id)) { - var row = (WixMediaTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixMedia); - row.DiskId_ = id; - row.CompressionLevel = compressionLevel; - row.Layout = layout; - } + DiskId = id, + DiskPrompt = diskPrompt, + Cabinet = cabinet, + VolumeLabel = volumeLabel, + Source = source, // the Source column is only set when creating a patch + CompressionLevel = compressionLevel, + Layout = layout + }; + + this.Core.AddTuple(tuple); if (null != symbols) { - var symbolRow = (WixDeltaPatchSymbolPathsTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixDeltaPatchSymbolPaths); - symbolRow.Id = id.ToString(CultureInfo.InvariantCulture); - symbolRow.Type = SymbolPathType.Media; - symbolRow.SymbolPaths = symbols; + this.Core.AddTuple(new WixDeltaPatchSymbolPathsTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, SymbolPathType.Media, id)) + { + SymbolType = SymbolPathType.Media, + SymbolId = id.ToString(CultureInfo.InvariantCulture), + SymbolPaths = symbols + }); } } } @@ -7518,8 +7483,8 @@ namespace WixToolset.Core string diskPrompt = null; var patch = null != patchId; string volumeLabel = null; - var maximumUncompressedMediaSize = CompilerConstants.IntegerNotSet; - var maximumCabinetSizeForLargeFileSplitting = CompilerConstants.IntegerNotSet; + int? maximumUncompressedMediaSize = null; + int? maximumCabinetSizeForLargeFileSplitting = null; CompressionLevel? compressionLevel = null; // this defaults to mszip in Binder var embedCab = patch ? YesNoType.Yes : YesNoType.NotSet; @@ -7572,7 +7537,7 @@ namespace WixToolset.Core maximumUncompressedMediaSize = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, Int32.MaxValue); break; case "MaximumCabinetSizeForLargeFileSplitting": - maximumCabinetSizeForLargeFileSplitting = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, CompilerCore.MinValueOfMaxCabSizeForLargeFileSplitting, CompilerCore.MaxValueOfMaxCabSizeForLargeFileSplitting); + maximumCabinetSizeForLargeFileSplitting = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, Compiler.MinValueOfMaxCabSizeForLargeFileSplitting, Compiler.MaxValueOfMaxCabSizeForLargeFileSplitting); break; default: this.Core.UnexpectedAttribute(node, attrib); @@ -7585,46 +7550,39 @@ namespace WixToolset.Core } } - if (YesNoType.IllegalValue != embedCab) + if (YesNoType.Yes == embedCab) { - if (YesNoType.Yes == embedCab) - { - cabinetTemplate = String.Concat("#", cabinetTemplate); - } + cabinetTemplate = String.Concat("#", cabinetTemplate); } if (!this.Core.EncounteredError) { - var temporaryMediaRow = (MediaTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Media, new Identifier(1, AccessModifier.Public)); - - var mediaTemplateRow = (WixMediaTemplateTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixMediaTemplate); - mediaTemplateRow.CabinetTemplate = cabinetTemplate; - mediaTemplateRow.VolumeLabel = volumeLabel; - mediaTemplateRow.DiskPrompt = diskPrompt; - mediaTemplateRow.VolumeLabel = volumeLabel; - - if (maximumUncompressedMediaSize != CompilerConstants.IntegerNotSet) - { - mediaTemplateRow.MaximumUncompressedMediaSize = maximumUncompressedMediaSize; - } - else + this.Core.AddTuple(new MediaTuple(sourceLineNumbers, new Identifier(AccessModifier.Public, 1)) { - mediaTemplateRow.MaximumUncompressedMediaSize = CompilerCore.DefaultMaximumUncompressedMediaSize; - } + DiskId = 1 + }); - if (maximumCabinetSizeForLargeFileSplitting != CompilerConstants.IntegerNotSet) - { - mediaTemplateRow.MaximumCabinetSizeForLargeFileSplitting = maximumCabinetSizeForLargeFileSplitting; - } - else + var tuple = new WixMediaTemplateTuple(sourceLineNumbers) { - mediaTemplateRow.MaximumCabinetSizeForLargeFileSplitting = 0; // Default value of 0 corresponds to max size of 2048 MB (i.e. 2 GB) - } + CabinetTemplate = cabinetTemplate, + VolumeLabel = volumeLabel, + DiskPrompt = diskPrompt, + MaximumUncompressedMediaSize = maximumUncompressedMediaSize, + MaximumCabinetSizeForLargeFileSplitting = maximumCabinetSizeForLargeFileSplitting, + CompressionLevel = compressionLevel + }; - if (compressionLevel.HasValue) - { - mediaTemplateRow.CompressionLevel = compressionLevel.Value; - } + //else + //{ + // mediaTemplateRow.MaximumUncompressedMediaSize = CompilerCore.DefaultMaximumUncompressedMediaSize; + //} + + //else + //{ + // mediaTemplateRow.MaximumCabinetSizeForLargeFileSplitting = 0; // Default value of 0 corresponds to max size of 2048 MB (i.e. 2 GB) + //} + + this.Core.AddTuple(tuple); } } @@ -7639,7 +7597,7 @@ namespace WixToolset.Core var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); Identifier id = null; var configData = String.Empty; - var fileCompression = YesNoType.NotSet; + bool? fileCompression = null; string language = null; string sourceFile = null; @@ -7657,7 +7615,7 @@ namespace WixToolset.Core this.Core.CreateSimpleReference(sourceLineNumbers, "Media", diskId.ToString(CultureInfo.InvariantCulture.NumberFormat)); break; case "FileCompression": - fileCompression = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + fileCompression = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); break; case "Language": language = this.Core.GetAttributeLocalizableIntegerValue(sourceLineNumbers, attrib, 0, Int16.MaxValue); @@ -7726,25 +7684,19 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixMerge, id); - row.Set(1, language); - row.Set(2, directoryId); - row.Set(3, sourceFile); - row.Set(4, diskId); - if (YesNoType.Yes == fileCompression) - { - row.Set(5, true); - } - else if (YesNoType.No == fileCompression) - { - row.Set(5, false); - } - else // YesNoType.NotSet == fileCompression + var tuple = new WixMergeTuple(sourceLineNumbers, id) { - // and we leave the column null - } - row.Set(6, configData); - row.Set(7, Guid.Empty.ToString("B")); + Directory_ = directoryId, + SourceFile = sourceFile, + DiskId = diskId, + ConfigurationData = configData, + FileCompression = fileCompression, + Feature_ = Guid.Empty.ToString("B") + }; + + tuple.Set((int)WixMergeTupleFields.Language, language); + + this.Core.AddTuple(tuple); } } @@ -7922,10 +7874,14 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MIME); - row.Set(0, contentType); - row.Set(1, extension); - row.Set(2, classId); + var tuple = new MIMETuple(sourceLineNumbers, new Identifier(AccessModifier.Private, contentType)) + { + ContentType = contentType, + Extension_ = extension, + CLSID = classId + }; + + this.Core.AddTuple(tuple); } } else if (YesNoType.No == advertise) @@ -7946,22 +7902,16 @@ namespace WixToolset.Core } /// - /// Parses a patch creation element. + /// Parses a patch property element. /// /// The element to parse. - private void ParsePatchCreationElement(XElement node) + /// True if parsing an patch element. + private void ParsePatchPropertyElement(XElement node, bool patch) { var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - var clean = true; // Default is to clean - var codepage = 0; - string outputPath = null; - var productMismatches = false; - var replaceGuids = String.Empty; - string sourceList = null; - string symbolFlags = null; - var targetProducts = String.Empty; - var versionMismatches = false; - var wholeFiles = false; + string name = null; + string company = null; + string value = null; foreach (var attrib in node.Attributes()) { @@ -7970,31 +7920,14 @@ namespace WixToolset.Core switch (attrib.Name.LocalName) { case "Id": - this.activeName = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false); - break; - case "AllowMajorVersionMismatches": - versionMismatches = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); - break; - case "AllowProductCodeMismatches": - productMismatches = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); - break; - case "CleanWorkingFolder": - clean = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); - break; - case "Codepage": - codepage = this.Core.GetAttributeCodePageValue(sourceLineNumbers, attrib); - break; - case "OutputPath": - outputPath = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "SourceList": - sourceList = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + case "Name": + name = this.Core.GetAttributeValue(sourceLineNumbers, attrib); break; - case "SymbolFlags": - symbolFlags = String.Format(CultureInfo.InvariantCulture, "0x{0:x8}", this.Core.GetAttributeLongValue(sourceLineNumbers, attrib, 0, UInt32.MaxValue)); + case "Company": + company = this.Core.GetAttributeValue(sourceLineNumbers, attrib); break; - case "WholeFilesOnly": - wholeFiles = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + case "Value": + value = this.Core.GetAttributeValue(sourceLineNumbers, attrib); break; default: this.Core.UnexpectedAttribute(node, attrib); @@ -8007,101 +7940,66 @@ namespace WixToolset.Core } } - if (null == this.activeName) + if (null == name) { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Name")); } - this.Core.CreateActiveSection(this.activeName, SectionType.PatchCreation, codepage, this.Context.CompilationId); - - foreach (var child in node.Elements()) + if (null == value) { - if (CompilerCore.WixNamespace == child.Name.Namespace) - { - switch (child.Name.LocalName) - { - case "Family": - this.ParseFamilyElement(child); - break; - case "PatchInformation": - this.ParsePatchInformationElement(child); - break; - case "PatchMetadata": - this.ParsePatchMetadataElement(child); - break; - case "PatchProperty": - this.ParsePatchPropertyElement(child, false); - break; - case "PatchSequence": - this.ParsePatchSequenceElement(child); - break; - case "ReplacePatch": - replaceGuids = String.Concat(replaceGuids, this.ParseReplacePatchElement(child)); - break; - case "TargetProductCode": - var targetProduct = this.ParseTargetProductCodeElement(child); - if (0 < targetProducts.Length) - { - targetProducts = String.Concat(targetProducts, ";"); - } - targetProducts = String.Concat(targetProducts, targetProduct); - break; - default: - this.Core.UnexpectedElement(node, child); - break; - } - } - else - { - this.Core.ParseExtensionElement(node, child); - } + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Value")); } - this.ProcessProperties(sourceLineNumbers, "PatchGUID", this.activeName); - this.ProcessProperties(sourceLineNumbers, "AllowProductCodeMismatches", productMismatches ? "1" : "0"); - this.ProcessProperties(sourceLineNumbers, "AllowProductVersionMajorMismatches", versionMismatches ? "1" : "0"); - this.ProcessProperties(sourceLineNumbers, "DontRemoveTempFolderWhenFinished", clean ? "0" : "1"); - this.ProcessProperties(sourceLineNumbers, "IncludeWholeFilesOnly", wholeFiles ? "1" : "0"); - - if (null != symbolFlags) - { - this.ProcessProperties(sourceLineNumbers, "ApiPatchingSymbolFlags", symbolFlags); - } + this.Core.ParseForExtensionElements(node); - if (0 < replaceGuids.Length) + if (patch) { - this.ProcessProperties(sourceLineNumbers, "ListOfPatchGUIDsToReplace", replaceGuids); + // /Patch/PatchProperty goes directly into MsiPatchMetadata table + this.Core.AddTuple(new MsiPatchMetadataTuple(sourceLineNumbers) + { + Company = company, + Property = name, + Value = value + }); } - - if (0 < targetProducts.Length) + else { - this.ProcessProperties(sourceLineNumbers, "ListOfTargetProductCodes", targetProducts); + if (null != company) + { + this.Core.Write(ErrorMessages.UnexpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Company")); + } + this.AddPrivateProperty(sourceLineNumbers, name, value); } + } - if (null != outputPath) + /// + /// Adds a row to the properties table. + /// + /// Source line numbers. + /// Name of the property. + /// Value of the property. + private void AddPrivateProperty(SourceLineNumber sourceLineNumbers, string name, string value) + { + if (!this.Core.EncounteredError) { - this.ProcessProperties(sourceLineNumbers, "PatchOutputPath", outputPath); - } + var tuple = new PropertyTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, name)) + { + Value = value + }; - if (null != sourceList) - { - this.ProcessProperties(sourceLineNumbers, "PatchSourceList", sourceList); + this.Core.AddTuple(tuple); } } /// - /// Parses a family element. + /// Parses a TargetProductCode element. /// /// The element to parse. - private void ParseFamilyElement(XElement node) + /// The id from the node. + private string ParseTargetProductCodeElement(XElement node) { var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - var diskId = CompilerConstants.IntegerNotSet; - string diskPrompt = null; - string mediaSrcProp = null; - string name = null; - var sequenceStart = CompilerConstants.IntegerNotSet; - string volumeLabel = null; + string id = null; foreach (var attrib in node.Attributes()) { @@ -8109,23 +8007,12 @@ namespace WixToolset.Core { switch (attrib.Name.LocalName) { - case "DiskId": - diskId = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, Int16.MaxValue); - break; - case "DiskPrompt": - diskPrompt = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "MediaSrcProp": - mediaSrcProp = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Name": - name = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "SequenceStart": - sequenceStart = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, Int32.MaxValue); - break; - case "VolumeLabel": - volumeLabel = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + case "Id": + id = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + if (id.Length > 0 && "*" != id) + { + id = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false); + } break; default: this.Core.UnexpectedAttribute(node, attrib); @@ -8138,1045 +8025,47 @@ namespace WixToolset.Core } } - if (null == name) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Name")); - } - else if (0 < name.Length) + if (null == id) { - if (8 < name.Length) // check the length - { - this.Core.Write(ErrorMessages.FamilyNameTooLong(sourceLineNumbers, node.Name.LocalName, "Name", name, name.Length)); - } - else // check for illegal characters - { - foreach (var character in name) - { - if (!Char.IsLetterOrDigit(character) && '_' != character) - { - this.Core.Write(ErrorMessages.IllegalFamilyName(sourceLineNumbers, node.Name.LocalName, "Name", name)); - } - } - } + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); } - foreach (var child in node.Elements()) + this.Core.ParseForExtensionElements(node); + + return id; + } + + /// + /// Parses a ReplacePatch element. + /// + /// The element to parse. + /// The id from the node. + private string ParseReplacePatchElement(XElement node) + { + var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + string id = null; + + foreach (var attrib in node.Attributes()) { - if (CompilerCore.WixNamespace == child.Name.Namespace) + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) { - switch (child.Name.LocalName) + switch (attrib.Name.LocalName) { - case "UpgradeImage": - this.ParseUpgradeImageElement(child, name); - break; - case "ExternalFile": - this.ParseExternalFileElement(child, name); - break; - case "ProtectFile": - this.ParseProtectFileElement(child, name); + case "Id": + id = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false); break; default: - this.Core.UnexpectedElement(node, child); + this.Core.UnexpectedAttribute(node, attrib); break; } } else { - this.Core.ParseExtensionElement(node, child); + this.Core.ParseExtensionAttribute(node, attrib); } } - if (!this.Core.EncounteredError) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ImageFamilies); - row.Set(0, name); - row.Set(1, mediaSrcProp); - if (CompilerConstants.IntegerNotSet != diskId) - { - row.Set(2, diskId); - } - - if (CompilerConstants.IntegerNotSet != sequenceStart) - { - row.Set(3, sequenceStart); - } - row.Set(4, diskPrompt); - row.Set(5, volumeLabel); - } - } - - /// - /// Parses an upgrade image element. - /// - /// The element to parse. - /// The family for this element. - private void ParseUpgradeImageElement(XElement node, string family) - { - var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - string sourceFile = null; - string sourcePatch = null; - var symbols = new List(); - string upgrade = null; - - foreach (var attrib in node.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Id": - upgrade = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - if (13 < upgrade.Length) - { - this.Core.Write(ErrorMessages.IdentifierTooLongError(sourceLineNumbers, node.Name.LocalName, "Id", upgrade, 13)); - } - break; - case "SourceFile": - case "src": - if (null != sourceFile) - { - this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, "src", "SourceFile")); - } - - if ("src" == attrib.Name.LocalName) - { - this.Core.Write(WarningMessages.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "SourceFile")); - } - sourceFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "SourcePatch": - case "srcPatch": - if (null != sourcePatch) - { - this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, "srcPatch", "SourcePatch")); - } - - if ("srcPatch" == attrib.Name.LocalName) - { - this.Core.Write(WarningMessages.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "SourcePatch")); - } - sourcePatch = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - default: - this.Core.UnexpectedAttribute(node, attrib); - break; - } - } - else - { - this.Core.ParseExtensionAttribute(node, attrib); - } - } - - if (null == upgrade) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); - } - - if (null == sourceFile) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "SourceFile")); - } - - foreach (var child in node.Elements()) - { - if (CompilerCore.WixNamespace == child.Name.Namespace) - { - switch (child.Name.LocalName) - { - case "SymbolPath": - symbols.Add(this.ParseSymbolPathElement(child)); - break; - case "TargetImage": - this.ParseTargetImageElement(child, upgrade, family); - break; - case "UpgradeFile": - this.ParseUpgradeFileElement(child, upgrade); - break; - default: - this.Core.UnexpectedElement(node, child); - break; - } - } - else - { - this.Core.ParseExtensionElement(node, child); - } - } - - if (!this.Core.EncounteredError) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.UpgradedImages); - row.Set(0, upgrade); - row.Set(1, sourceFile); - row.Set(2, sourcePatch); - row.Set(3, String.Join(";", symbols)); - row.Set(4, family); - } - } - - /// - /// Parses an upgrade file element. - /// - /// The element to parse. - /// The upgrade key for this element. - private void ParseUpgradeFileElement(XElement node, string upgrade) - { - var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - var allowIgnoreOnError = false; - string file = null; - var ignore = false; - var symbols = new List(); - var wholeFile = false; - - foreach (var attrib in node.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "AllowIgnoreOnError": - allowIgnoreOnError = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); - break; - case "File": - file = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Ignore": - ignore = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); - break; - case "WholeFile": - wholeFile = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); - break; - default: - this.Core.UnexpectedAttribute(node, attrib); - break; - } - } - else - { - this.Core.ParseExtensionAttribute(node, attrib); - } - } - - if (null == file) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "File")); - } - - foreach (var child in node.Elements()) - { - if (CompilerCore.WixNamespace == child.Name.Namespace) - { - switch (child.Name.LocalName) - { - case "SymbolPath": - symbols.Add(this.ParseSymbolPathElement(child)); - break; - default: - this.Core.UnexpectedElement(node, child); - break; - } - } - else - { - this.Core.ParseExtensionElement(node, child); - } - } - - if (!this.Core.EncounteredError) - { - if (ignore) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.UpgradedFilesToIgnore); - row.Set(0, upgrade); - row.Set(1, file); - } - else - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.UpgradedFiles_OptionalData); - row.Set(0, upgrade); - row.Set(1, file); - row.Set(2, String.Join(";", symbols)); - row.Set(3, allowIgnoreOnError ? 1 : 0); - row.Set(4, wholeFile ? 1 : 0); - } - } - } - - /// - /// Parses a target image element. - /// - /// The element to parse. - /// The upgrade key for this element. - /// The family key for this element. - private void ParseTargetImageElement(XElement node, string upgrade, string family) - { - var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - var ignore = false; - var order = CompilerConstants.IntegerNotSet; - string sourceFile = null; - string symbols = null; - string target = null; - string validation = null; - - foreach (var attrib in node.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Id": - target = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - if (target.Length > 13) - { - this.Core.Write(ErrorMessages.IdentifierTooLongError(sourceLineNumbers, node.Name.LocalName, "Id", target, 13)); - } - break; - case "IgnoreMissingFiles": - ignore = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); - break; - case "Order": - order = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, Int32.MinValue + 2, Int32.MaxValue); - break; - case "SourceFile": - case "src": - if (null != sourceFile) - { - this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, "src", "SourceFile")); - } - - if ("src" == attrib.Name.LocalName) - { - this.Core.Write(WarningMessages.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "SourceFile")); - } - sourceFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Validation": - validation = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - default: - this.Core.UnexpectedAttribute(node, attrib); - break; - } - } - else - { - this.Core.ParseExtensionAttribute(node, attrib); - } - } - - if (null == target) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); - } - - if (null == sourceFile) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "SourceFile")); - } - - if (CompilerConstants.IntegerNotSet == order) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Order")); - } - - foreach (var child in node.Elements()) - { - if (CompilerCore.WixNamespace == child.Name.Namespace) - { - switch (child.Name.LocalName) - { - case "SymbolPath": - if (null != symbols) - { - symbols = String.Concat(symbols, ";", this.ParseSymbolPathElement(child)); - } - else - { - symbols = this.ParseSymbolPathElement(child); - } - break; - case "TargetFile": - this.ParseTargetFileElement(child, target, family); - break; - default: - this.Core.UnexpectedElement(node, child); - break; - } - } - else - { - this.Core.ParseExtensionElement(node, child); - } - } - - if (!this.Core.EncounteredError) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.TargetImages); - row.Set(0, target); - row.Set(1, sourceFile); - row.Set(2, symbols); - row.Set(3, upgrade); - row.Set(4, order); - row.Set(5, validation); - row.Set(6, ignore ? 1 : 0); - } - } - - /// - /// Parses an upgrade file element. - /// - /// The element to parse. - /// The upgrade key for this element. - /// The family key for this element. - private void ParseTargetFileElement(XElement node, string target, string family) - { - var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - string file = null; - string ignoreLengths = null; - string ignoreOffsets = null; - string protectLengths = null; - string protectOffsets = null; - string symbols = null; - - foreach (var attrib in node.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Id": - file = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - default: - this.Core.UnexpectedAttribute(node, attrib); - break; - } - } - else - { - this.Core.ParseExtensionAttribute(node, attrib); - } - } - - if (null == file) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); - } - - foreach (var child in node.Elements()) - { - if (CompilerCore.WixNamespace == child.Name.Namespace) - { - switch (child.Name.LocalName) - { - case "IgnoreRange": - this.ParseRangeElement(child, ref ignoreOffsets, ref ignoreLengths); - break; - case "ProtectRange": - this.ParseRangeElement(child, ref protectOffsets, ref protectLengths); - break; - case "SymbolPath": - symbols = this.ParseSymbolPathElement(child); - break; - default: - this.Core.UnexpectedElement(node, child); - break; - } - } - else - { - this.Core.ParseExtensionElement(node, child); - } - } - - if (!this.Core.EncounteredError) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.TargetFiles_OptionalData); - row.Set(0, target); - row.Set(1, file); - row.Set(2, symbols); - row.Set(3, ignoreOffsets); - row.Set(4, ignoreLengths); - - if (null != protectOffsets) - { - row.Set(5, protectOffsets); - - var row2 = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.FamilyFileRanges); - row2.Set(0, family); - row2.Set(1, file); - row2.Set(2, protectOffsets); - row2.Set(3, protectLengths); - } - } - } - - /// - /// Parses an external file element. - /// - /// The element to parse. - /// The family for this element. - private void ParseExternalFileElement(XElement node, string family) - { - var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - string file = null; - string ignoreLengths = null; - string ignoreOffsets = null; - var order = CompilerConstants.IntegerNotSet; - string protectLengths = null; - string protectOffsets = null; - string source = null; - string symbols = null; - - foreach (var attrib in node.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "File": - file = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Order": - order = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, Int32.MinValue + 2, Int32.MaxValue); - break; - case "Source": - case "src": - if (null != source) - { - this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, "src", "Source")); - } - - if ("src" == attrib.Name.LocalName) - { - this.Core.Write(WarningMessages.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "Source")); - } - source = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - default: - this.Core.UnexpectedAttribute(node, attrib); - break; - } - } - else - { - this.Core.ParseExtensionAttribute(node, attrib); - } - } - - if (null == file) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "File")); - } - - if (null == source) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Source")); - } - - if (CompilerConstants.IntegerNotSet == order) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Order")); - } - - foreach (var child in node.Elements()) - { - if (CompilerCore.WixNamespace == child.Name.Namespace) - { - switch (child.Name.LocalName) - { - case "IgnoreRange": - this.ParseRangeElement(child, ref ignoreOffsets, ref ignoreLengths); - break; - case "ProtectRange": - this.ParseRangeElement(child, ref protectOffsets, ref protectLengths); - break; - case "SymbolPath": - symbols = this.ParseSymbolPathElement(child); - break; - default: - this.Core.UnexpectedElement(node, child); - break; - } - } - else - { - this.Core.ParseExtensionElement(node, child); - } - } - - if (!this.Core.EncounteredError) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ExternalFiles); - row.Set(0, family); - row.Set(1, file); - row.Set(2, source); - row.Set(3, symbols); - row.Set(4, ignoreOffsets); - row.Set(5, ignoreLengths); - if (null != protectOffsets) - { - row.Set(6, protectOffsets); - } - - if (CompilerConstants.IntegerNotSet != order) - { - row.Set(7, order); - } - - if (null != protectOffsets) - { - var row2 = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.FamilyFileRanges); - row2.Set(0, family); - row2.Set(1, file); - row2.Set(2, protectOffsets); - row2.Set(3, protectLengths); - } - } - } - - /// - /// Parses a protect file element. - /// - /// The element to parse. - /// The family for this element. - private void ParseProtectFileElement(XElement node, string family) - { - var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - string file = null; - string protectLengths = null; - string protectOffsets = null; - - foreach (var attrib in node.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "File": - file = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - default: - this.Core.UnexpectedAttribute(node, attrib); - break; - } - } - else - { - this.Core.ParseExtensionAttribute(node, attrib); - } - } - - if (null == file) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "File")); - } - - foreach (var child in node.Elements()) - { - if (CompilerCore.WixNamespace == child.Name.Namespace) - { - switch (child.Name.LocalName) - { - case "ProtectRange": - this.ParseRangeElement(child, ref protectOffsets, ref protectLengths); - break; - default: - this.Core.UnexpectedElement(node, child); - break; - } - } - else - { - this.Core.ParseExtensionElement(node, child); - } - } - - if (null == protectOffsets || null == protectLengths) - { - this.Core.Write(ErrorMessages.ExpectedElement(sourceLineNumbers, node.Name.LocalName, "ProtectRange")); - } - - if (!this.Core.EncounteredError) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.FamilyFileRanges); - row.Set(0, family); - row.Set(1, file); - row.Set(2, protectOffsets); - row.Set(3, protectLengths); - } - } - - /// - /// Parses a range element (ProtectRange, IgnoreRange, etc). - /// - /// The element to parse. - /// Reference to the offsets string. - /// Reference to the lengths string. - private void ParseRangeElement(XElement node, ref string offsets, ref string lengths) - { - var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - string length = null; - string offset = null; - - foreach (var attrib in node.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Length": - length = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Offset": - offset = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - default: - this.Core.UnexpectedAttribute(node, attrib); - break; - } - } - else - { - this.Core.ParseExtensionAttribute(node, attrib); - } - } - - if (null == length) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Length")); - } - - if (null == offset) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Offset")); - } - - this.Core.ParseForExtensionElements(node); - - if (null != lengths) - { - lengths = String.Concat(lengths, ",", length); - } - else - { - lengths = length; - } - - if (null != offsets) - { - offsets = String.Concat(offsets, ",", offset); - } - else - { - offsets = offset; - } - } - - /// - /// Parses a patch property element. - /// - /// The element to parse. - /// True if parsing an patch element. - private void ParsePatchPropertyElement(XElement node, bool patch) - { - var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - string name = null; - string company = null; - string value = null; - - foreach (var attrib in node.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Id": - case "Name": - name = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Company": - company = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Value": - value = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - default: - this.Core.UnexpectedAttribute(node, attrib); - break; - } - } - else - { - this.Core.ParseExtensionAttribute(node, attrib); - } - } - - if (null == name) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Name")); - } - - if (null == value) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Value")); - } - - this.Core.ParseForExtensionElements(node); - - if (patch) - { - // /Patch/PatchProperty goes directly into MsiPatchMetadata table - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiPatchMetadata); - row.Set(0, company); - row.Set(1, name); - row.Set(2, value); - } - else - { - if (null != company) - { - this.Core.Write(ErrorMessages.UnexpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Company")); - } - this.ProcessProperties(sourceLineNumbers, name, value); - } - } - - /// - /// Parses a patch sequence element. - /// - /// The element to parse. - private void ParsePatchSequenceElement(XElement node) - { - var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - string family = null; - string target = null; - string sequence = null; - var attributes = 0; - - foreach (var attrib in node.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "PatchFamily": - family = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); - break; - case "ProductCode": - if (null != target) - { - this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "Target", "TargetImage")); - } - target = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false); - break; - case "Target": - if (null != target) - { - this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "TargetImage", "ProductCode")); - } - this.Core.Write(WarningMessages.DeprecatedPatchSequenceTargetAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); - target = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "TargetImage": - if (null != target) - { - this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "Target", "ProductCode")); - } - target = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - this.Core.CreateSimpleReference(sourceLineNumbers, "TargetImages", target); - break; - case "Sequence": - sequence = this.Core.GetAttributeVersionValue(sourceLineNumbers, attrib); - break; - case "Supersede": - if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - attributes |= 0x1; - } - break; - default: - this.Core.UnexpectedAttribute(node, attrib); - break; - } - } - else - { - this.Core.ParseExtensionAttribute(node, attrib); - } - } - - if (null == family) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "PatchFamily")); - } - - this.Core.ParseForExtensionElements(node); - - if (!this.Core.EncounteredError) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PatchSequence); - row.Set(0, family); - row.Set(1, target); - if (!String.IsNullOrEmpty(sequence)) - { - row.Set(2, sequence); - } - row.Set(3, attributes); - } - } - - /// - /// Parses a TargetProductCode element. - /// - /// The element to parse. - /// The id from the node. - private string ParseTargetProductCodeElement(XElement node) - { - var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - string id = null; - - foreach (var attrib in node.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Id": - id = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - if (id.Length > 0 && "*" != id) - { - id = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false); - } - break; - default: - this.Core.UnexpectedAttribute(node, attrib); - break; - } - } - else - { - this.Core.ParseExtensionAttribute(node, attrib); - } - } - - if (null == id) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); - } - - this.Core.ParseForExtensionElements(node); - - return id; - } - - /// - /// Parses a TargetProductCodes element. - /// - /// The element to parse. - private void ParseTargetProductCodesElement(XElement node) - { - var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - var replace = false; - var targetProductCodes = new List(); - - foreach (var attrib in node.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Replace": - replace = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); - break; - default: - this.Core.UnexpectedAttribute(node, attrib); - break; - } - } - else - { - this.Core.ParseExtensionAttribute(node, attrib); - } - } - - foreach (var child in node.Elements()) - { - if (CompilerCore.WixNamespace == child.Name.Namespace) - { - switch (child.Name.LocalName) - { - case "TargetProductCode": - var id = this.ParseTargetProductCodeElement(child); - if (0 == String.CompareOrdinal("*", id)) - { - this.Core.Write(ErrorMessages.IllegalAttributeValueWhenNested(sourceLineNumbers, child.Name.LocalName, "Id", id, node.Name.LocalName)); - } - else - { - targetProductCodes.Add(id); - } - break; - default: - this.Core.UnexpectedElement(node, child); - break; - } - } - else - { - this.Core.ParseExtensionElement(node, child); - } - } - - if (!this.Core.EncounteredError) - { - // By default, target ProductCodes should be added. - if (!replace) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixPatchTarget); - row.Set(0, "*"); - } - - foreach (var targetProductCode in targetProductCodes) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixPatchTarget); - row.Set(0, targetProductCode); - } - } - } - - /// - /// Parses a ReplacePatch element. - /// - /// The element to parse. - /// The id from the node. - private string ParseReplacePatchElement(XElement node) - { - var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - string id = null; - - foreach (var attrib in node.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Id": - id = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false); - break; - default: - this.Core.UnexpectedAttribute(node, attrib); - break; - } - } - else - { - this.Core.ParseExtensionAttribute(node, attrib); - } - } - - if (null == id) + if (null == id) { this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); } @@ -9226,402 +8115,6 @@ namespace WixToolset.Core return path; } - /// - /// Parses an patch element. - /// - /// The element to parse. - private void ParsePatchElement(XElement node) - { - var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - string patchId = null; - var codepage = 0; - ////bool versionMismatches = false; - ////bool productMismatches = false; - var allowRemoval = false; - string classification = null; - string clientPatchId = null; - string description = null; - string displayName = null; - string comments = null; - string manufacturer = null; - var minorUpdateTargetRTM = YesNoType.NotSet; - string moreInfoUrl = null; - var optimizeCA = CompilerConstants.IntegerNotSet; - var optimizedInstallMode = YesNoType.NotSet; - string targetProductName = null; - // string replaceGuids = String.Empty; - var apiPatchingSymbolFlags = 0; - var optimizePatchSizeForLargeFiles = false; - - foreach (var attrib in node.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Id": - patchId = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, true); - break; - case "Codepage": - codepage = this.Core.GetAttributeCodePageValue(sourceLineNumbers, attrib); - break; - case "AllowMajorVersionMismatches": - ////versionMismatches = (YesNoType.Yes == this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib)); - break; - case "AllowProductCodeMismatches": - ////productMismatches = (YesNoType.Yes == this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib)); - break; - case "AllowRemoval": - allowRemoval = (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)); - break; - case "Classification": - classification = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "ClientPatchId": - clientPatchId = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Description": - description = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "DisplayName": - displayName = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Comments": - comments = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Manufacturer": - manufacturer = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "MinorUpdateTargetRTM": - minorUpdateTargetRTM = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); - break; - case "MoreInfoURL": - moreInfoUrl = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "OptimizedInstallMode": - optimizedInstallMode = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); - break; - case "TargetProductName": - targetProductName = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "ApiPatchingSymbolNoImagehlpFlag": - apiPatchingSymbolFlags |= (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) ? (int)PatchSymbolFlagsType.PATCH_SYMBOL_NO_IMAGEHLP : 0; - break; - case "ApiPatchingSymbolNoFailuresFlag": - apiPatchingSymbolFlags |= (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) ? (int)PatchSymbolFlagsType.PATCH_SYMBOL_NO_FAILURES : 0; - break; - case "ApiPatchingSymbolUndecoratedTooFlag": - apiPatchingSymbolFlags |= (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) ? (int)PatchSymbolFlagsType.PATCH_SYMBOL_UNDECORATED_TOO : 0; - break; - case "OptimizePatchSizeForLargeFiles": - optimizePatchSizeForLargeFiles = (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)); - break; - default: - this.Core.UnexpectedAttribute(node, attrib); - break; - } - } - else - { - this.Core.ParseExtensionAttribute(node, attrib); - } - } - - if (patchId == null || patchId == "*") - { - // auto-generate at compile time, since this value gets dispersed to several locations - patchId = Common.GenerateGuid(); - } - this.activeName = patchId; - - if (null == this.activeName) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); - } - if (null == classification) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Classification")); - } - if (null == clientPatchId) - { - clientPatchId = String.Concat("_", new Guid(patchId).ToString("N", CultureInfo.InvariantCulture).ToUpper(CultureInfo.InvariantCulture)); - } - if (null == description) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Description")); - } - if (null == displayName) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "DisplayName")); - } - if (null == manufacturer) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Manufacturer")); - } - - this.Core.CreateActiveSection(this.activeName, SectionType.Patch, codepage, this.Context.CompilationId); - - foreach (var child in node.Elements()) - { - if (CompilerCore.WixNamespace == child.Name.Namespace) - { - switch (child.Name.LocalName) - { - case "PatchInformation": - this.ParsePatchInformationElement(child); - break; - case "Media": - this.ParseMediaElement(child, patchId); - break; - case "OptimizeCustomActions": - optimizeCA = this.ParseOptimizeCustomActionsElement(child); - break; - case "PatchFamily": - this.ParsePatchFamilyElement(child, ComplexReferenceParentType.Patch, patchId); - break; - case "PatchFamilyRef": - this.ParsePatchFamilyRefElement(child, ComplexReferenceParentType.Patch, patchId); - break; - case "PatchFamilyGroup": - this.ParsePatchFamilyGroupElement(child, ComplexReferenceParentType.Patch, patchId); - break; - case "PatchFamilyGroupRef": - this.ParsePatchFamilyGroupRefElement(child, ComplexReferenceParentType.Patch, patchId); - break; - case "PatchProperty": - this.ParsePatchPropertyElement(child, true); - break; - case "TargetProductCodes": - this.ParseTargetProductCodesElement(child); - break; - default: - this.Core.UnexpectedElement(node, child); - break; - } - } - else - { - this.Core.ParseExtensionElement(node, child); - } - } - - if (!this.Core.EncounteredError) - { - var patchIdRow = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixPatchId); - patchIdRow.Set(0, patchId); - patchIdRow.Set(1, clientPatchId); - patchIdRow.Set(2, optimizePatchSizeForLargeFiles); - patchIdRow.Set(3, apiPatchingSymbolFlags); - - if (allowRemoval) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiPatchMetadata); - row.Set(1, "AllowRemoval"); - row.Set(2, allowRemoval ? "1" : "0"); - } - - if (null != classification) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiPatchMetadata); - row.Set(1, "Classification"); - row.Set(2, classification); - } - - // always generate the CreationTimeUTC - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiPatchMetadata); - row.Set(1, "CreationTimeUTC"); - row.Set(2, DateTime.UtcNow.ToString("MM-dd-yy HH:mm", CultureInfo.InvariantCulture)); - } - - if (null != description) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiPatchMetadata); - row.Set(1, "Description"); - row.Set(2, description); - } - - if (null != displayName) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiPatchMetadata); - row.Set(1, "DisplayName"); - row.Set(2, displayName); - } - - if (null != manufacturer) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiPatchMetadata); - row.Set(1, "ManufacturerName"); - row.Set(2, manufacturer); - } - - if (YesNoType.NotSet != minorUpdateTargetRTM) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiPatchMetadata); - row.Set(1, "MinorUpdateTargetRTM"); - row.Set(2, YesNoType.Yes == minorUpdateTargetRTM ? "1" : "0"); - } - - if (null != moreInfoUrl) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiPatchMetadata); - row.Set(1, "MoreInfoURL"); - row.Set(2, moreInfoUrl); - } - - if (CompilerConstants.IntegerNotSet != optimizeCA) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiPatchMetadata); - row.Set(1, "OptimizeCA"); - row.Set(2, optimizeCA.ToString(CultureInfo.InvariantCulture)); - } - - if (YesNoType.NotSet != optimizedInstallMode) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiPatchMetadata); - row.Set(1, "OptimizedInstallMode"); - row.Set(2, YesNoType.Yes == optimizedInstallMode ? "1" : "0"); - } - - if (null != targetProductName) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiPatchMetadata); - row.Set(1, "TargetProductName"); - row.Set(2, targetProductName); - } - - if (null != comments) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixPatchMetadata); - row.Set(0, "Comments"); - row.Set(1, comments); - } - } - // TODO: do something with versionMismatches and productMismatches - } - - /// - /// Parses a PatchFamily element. - /// - /// The element to parse. - private void ParsePatchFamilyElement(XElement node, ComplexReferenceParentType parentType, string parentId) - { - var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - Identifier id = null; - string productCode = null; - string version = null; - var attributes = 0; - - foreach (var attrib in node.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Id": - id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib); - break; - case "ProductCode": - productCode = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false); - break; - case "Version": - version = this.Core.GetAttributeVersionValue(sourceLineNumbers, attrib); - break; - case "Supersede": - if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - attributes |= 0x1; - } - break; - default: - this.Core.UnexpectedAttribute(node, attrib); - break; - } - } - else - { - this.Core.ParseExtensionAttribute(node, attrib); - } - } - - if (null == id) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); - id = Identifier.Invalid; - } - - if (String.IsNullOrEmpty(version)) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Version")); - } - else if (!CompilerCore.IsValidProductVersion(version)) - { - this.Core.Write(ErrorMessages.InvalidProductVersion(sourceLineNumbers, version)); - } - - // find unexpected child elements - foreach (var child in node.Elements()) - { - if (CompilerCore.WixNamespace == child.Name.Namespace) - { - switch (child.Name.LocalName) - { - case "All": - this.ParseAllElement(child); - break; - case "BinaryRef": - this.ParsePatchChildRefElement(child, "Binary"); - break; - case "ComponentRef": - this.ParsePatchChildRefElement(child, "Component"); - break; - case "CustomActionRef": - this.ParsePatchChildRefElement(child, "CustomAction"); - break; - case "DirectoryRef": - this.ParsePatchChildRefElement(child, "Directory"); - break; - case "DigitalCertificateRef": - this.ParsePatchChildRefElement(child, "MsiDigitalCertificate"); - break; - case "FeatureRef": - this.ParsePatchChildRefElement(child, "Feature"); - break; - case "IconRef": - this.ParsePatchChildRefElement(child, "Icon"); - break; - case "PropertyRef": - this.ParsePatchChildRefElement(child, "Property"); - break; - case "UIRef": - this.ParsePatchChildRefElement(child, "WixUI"); - break; - default: - this.Core.UnexpectedElement(node, child); - break; - } - } - else - { - this.Core.ParseExtensionElement(node, child); - } - } - - - if (!this.Core.EncounteredError) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiPatchSequence, id); - row.Set(1, productCode); - row.Set(2, version); - row.Set(3, attributes); - - if (ComplexReferenceParentType.Unknown != parentType) - { - this.Core.CreateComplexReference(sourceLineNumbers, parentType, parentId, null, ComplexReferenceChildType.PatchFamily, id.Id, ComplexReferenceParentType.Patch == parentType); - } - } - } - /// /// Parses the All element under a PatchFamily. /// @@ -9650,7 +8143,13 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - this.Core.CreatePatchFamilyChildReference(sourceLineNumbers, "*", "*"); + var tuple = new WixPatchRefTuple(sourceLineNumbers) + { + Table = "*", + PrimaryKeys = "*" + }; + + this.Core.AddTuple(tuple); } } @@ -9693,7 +8192,13 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - this.Core.CreatePatchFamilyChildReference(sourceLineNumbers, tableName, id); + var tuple = new WixPatchRefTuple(sourceLineNumbers) + { + Table = tableName, + PrimaryKeys = id + }; + + this.Core.AddTuple(tuple); } } @@ -9770,9 +8275,13 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixPatchBaseline, id); - row.Set(1, diskId); - row.Set(2, (int)validationFlags); + var tuple = new WixPatchBaselineTuple(sourceLineNumbers, id) + { + DiskId = diskId, + ValidationFlags = validationFlags + }; + + this.Core.AddTuple(tuple); } } @@ -9948,21 +8457,5 @@ namespace WixToolset.Core } } } - - /// - /// Adds a row to the properties table. - /// - /// Source line numbers. - /// Name of the property. - /// Value of the property. - private void ProcessProperties(SourceLineNumber sourceLineNumbers, string name, string value) - { - if (!this.Core.EncounteredError) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Properties); - row.Set(0, name); - row.Set(1, value); - } - } } } diff --git a/src/WixToolset.Core/CompilerCore.cs b/src/WixToolset.Core/CompilerCore.cs index ea235a97..e87ad886 100644 --- a/src/WixToolset.Core/CompilerCore.cs +++ b/src/WixToolset.Core/CompilerCore.cs @@ -17,7 +17,6 @@ namespace WixToolset.Core using WixToolset.Extensibility; using WixToolset.Extensibility.Data; using WixToolset.Extensibility.Services; - using Wix = WixToolset.Data.Serialize; internal enum ValueListKind { @@ -50,9 +49,7 @@ namespace WixToolset.Core private const string IllegalLongFilenameCharacters = @"[\\\?|><:/\*""]"; // illegal: \ ? | > < : / * " private static readonly Regex IllegalLongFilename = new Regex(IllegalLongFilenameCharacters, RegexOptions.Compiled); - public const int DefaultMaximumUncompressedMediaSize = 200; // Default value is 200 MB - public const int MinValueOfMaxCabSizeForLargeFileSplitting = 20; // 20 MB - public const int MaxValueOfMaxCabSizeForLargeFileSplitting = 2 * 1024; // 2048 MB (i.e. 2 GB) + //public const int DefaultMaximumUncompressedMediaSize = 200; // Default value is 200 MB // Built-in variables (from burn\engine\variable.cpp, "vrgBuiltInVariables", around line 113) @@ -354,43 +351,20 @@ namespace WixToolset.Core } /// - /// Creates a row in the active section. + /// Creates a tuple in the active section. /// /// Source and line number of current row. - /// Name of table to create row in. - /// New row. - public IntermediateTuple CreateRow(SourceLineNumber sourceLineNumbers, TupleDefinitionType tupleType, Identifier identifier = null) - { - return this.CreateRow(sourceLineNumbers, tupleType, this.ActiveSection, identifier); - } - - /// - /// Creates a row in the active given . - /// - /// Source and line number of current row. - /// Name of table to create row in. - /// The section to which the row is added. If null, the row is added to the active section. - /// New row. - internal IntermediateTuple CreateRow(SourceLineNumber sourceLineNumbers, TupleDefinitionType tupleType, IntermediateSection section, Identifier identifier = null) + /// Type of tuple to create. + /// Optional identifier. + /// New tuple. + public IntermediateTuple CreateTuple(SourceLineNumber sourceLineNumbers, TupleDefinitionType tupleType, Identifier identifier = null) { var tupleDefinition = TupleDefinitions.ByType(tupleType); - var row = tupleDefinition.CreateTuple(sourceLineNumbers, identifier); + var tuple = tupleDefinition.CreateTuple(sourceLineNumbers, identifier); - if (null != identifier) - { - if (row.Definition.FieldDefinitions[0].Type == IntermediateFieldType.Number) - { - row.Set(0, Convert.ToInt32(identifier.Id)); - } - else - { - row.Set(0, identifier.Id); - } - } - - section.Tuples.Add(row); + this.ActiveSection.Tuples.Add(tuple); - return row; + return tuple; } /// @@ -405,20 +379,6 @@ namespace WixToolset.Core return this.parseHelper.CreateDirectoryReferenceFromInlineSyntax(this.ActiveSection, sourceLineNumbers, parentId, attribute, this.activeSectionInlinedDirectoryIds); } - /// - /// Creates a patch resource reference to the list of resoures to be filtered when producing a patch. This method should only be used when processing children of a patch family. - /// - /// Source and line number of current row. - /// Name of table to create row in. - /// Array of keys that make up the primary key of the table. - /// New row. - public void CreatePatchFamilyChildReference(SourceLineNumber sourceLineNumbers, string tableName, params string[] primaryKeys) - { - var patchReferenceRow = this.CreateRow(sourceLineNumbers, TupleDefinitionType.WixPatchRef); - patchReferenceRow.Set(0, tableName); - patchReferenceRow.Set(1, String.Join("/", primaryKeys)); - } - /// /// Creates a Registry row in the active section. /// @@ -430,7 +390,7 @@ namespace WixToolset.Core /// The component which will control installation/uninstallation of the registry entry. public Identifier CreateRegistryRow(SourceLineNumber sourceLineNumbers, RegistryRootType root, string key, string name, string value, string componentId) { - return this.parseHelper.CreateRegistryRow(this.ActiveSection, sourceLineNumbers, root, key, name, value, componentId, true); + return this.parseHelper.CreateRegistryTuple(this.ActiveSection, sourceLineNumbers, root, key, name, value, componentId, true); } /// @@ -466,7 +426,7 @@ namespace WixToolset.Core { if (!this.EncounteredError) { - this.parseHelper.CreateWixGroupRow(this.ActiveSection, sourceLineNumbers, parentType, parentId, childType, childId); + this.parseHelper.CreateWixGroupTuple(this.ActiveSection, sourceLineNumbers, parentType, parentId, childType, childId); } } @@ -752,39 +712,6 @@ namespace WixToolset.Core return this.parseHelper.GetAttributeYesNoDefaultValue(sourceLineNumbers, attribute); } - /// - /// Gets a yes/no/always value and displays an error for an illegal value. - /// - /// Source line information about the owner element. - /// The attribute containing the value to get. - /// The attribute's YesNoAlwaysType value. - [SuppressMessage("Microsoft.Design", "CA1059:MembersShouldNotExposeCertainConcreteTypes")] - public YesNoAlwaysType GetAttributeYesNoAlwaysValue(SourceLineNumber sourceLineNumbers, XAttribute attribute) - { - string value = this.GetAttributeValue(sourceLineNumbers, attribute); - - if (0 < value.Length) - { - switch (Wix.Enums.ParseYesNoAlwaysType(value)) - { - case Wix.YesNoAlwaysType.@always: - return YesNoAlwaysType.Always; - case Wix.YesNoAlwaysType.no: - return YesNoAlwaysType.No; - case Wix.YesNoAlwaysType.yes: - return YesNoAlwaysType.Yes; - case Wix.YesNoAlwaysType.NotSet: - // Previous code never returned 'NotSet'! - break; - default: - this.Write(ErrorMessages.IllegalYesNoAlwaysValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value)); - break; - } - } - - return YesNoAlwaysType.IllegalValue; - } - /// /// Gets a short filename value and displays an error for an illegal short filename value. /// @@ -854,57 +781,6 @@ namespace WixToolset.Core return this.parseHelper.GetAttributeRegistryRootValue(sourceLineNumbers, attribute, allowHkmu); } - /// - /// Gets an InstallUninstallType value and displays an error for an illegal value. - /// - /// Source line information about the owner element. - /// The attribute containing the value to get. - /// The attribute's InstallUninstallType value. - [SuppressMessage("Microsoft.Design", "CA1059:MembersShouldNotExposeCertainConcreteTypes")] - public Wix.InstallUninstallType GetAttributeInstallUninstallValue(SourceLineNumber sourceLineNumbers, XAttribute attribute) - { - Wix.InstallUninstallType installUninstall = Wix.InstallUninstallType.NotSet; - string value = this.GetAttributeValue(sourceLineNumbers, attribute); - - if (0 < value.Length) - { - installUninstall = Wix.Enums.ParseInstallUninstallType(value); - - if (Wix.InstallUninstallType.IllegalValue == installUninstall) - { - // TODO: Find a way to expose the valid values programatically! - this.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value, - "install", "uninstall", "both")); - } - } - - return installUninstall; - } - - /// - /// Gets an ExitType value and displays an error for an illegal value. - /// - /// Source line information about the owner element. - /// The attribute containing the value to get. - /// The attribute's ExitType value. - [SuppressMessage("Microsoft.Design", "CA1059:MembersShouldNotExposeCertainConcreteTypes")] - public Wix.ExitType GetAttributeExitValue(SourceLineNumber sourceLineNumbers, XAttribute attribute) - { - string value = this.GetAttributeValue(sourceLineNumbers, attribute); - - Wix.ExitType result = Wix.ExitType.NotSet; - if (!Enum.TryParse(value, out result)) - { - result = Wix.ExitType.IllegalValue; - - // TODO: Find a way to expose the valid values programatically! - this.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value, - "success", "cancel", "error", "suspend")); - } - - return result; - } - /// /// Gets a Bundle variable value and displays an error for an illegal value. /// @@ -1062,7 +938,7 @@ namespace WixToolset.Core internal void VerifyRequiredVersion(SourceLineNumber sourceLineNumbers, string requiredVersion) { // an null or empty string means any version will work - if (!string.IsNullOrEmpty(requiredVersion)) + if (!String.IsNullOrEmpty(requiredVersion)) { Assembly caller = Assembly.GetCallingAssembly(); AssemblyName name = caller.GetName(); @@ -1147,7 +1023,7 @@ namespace WixToolset.Core /// Identifier for the newly created row. internal Identifier CreateDirectoryRow(SourceLineNumber sourceLineNumbers, Identifier id, string parentId, string name, string shortName = null, string sourceName = null, string shortSourceName = null) { - return this.parseHelper.CreateDirectoryRow(this.ActiveSection, sourceLineNumbers, id, parentId, name, this.activeSectionInlinedDirectoryIds, shortName, sourceName, shortSourceName); + return this.parseHelper.CreateDirectoryTuple(this.ActiveSection, sourceLineNumbers, id, parentId, name, this.activeSectionInlinedDirectoryIds, shortName, sourceName, shortSourceName); } /// diff --git a/src/WixToolset.Core/Compiler_2.cs b/src/WixToolset.Core/Compiler_2.cs index 32768aca..c1c189ca 100644 --- a/src/WixToolset.Core/Compiler_2.cs +++ b/src/WixToolset.Core/Compiler_2.cs @@ -20,19 +20,21 @@ namespace WixToolset.Core internal partial class Compiler : ICompiler { /// - /// Parses an odbc driver or translator element. + /// Parses a product element. /// /// Element to parse. - /// Identifier of parent component. - /// Default identifer for driver/translator file. - /// Table we're processing for. - private void ParseODBCDriverOrTranslator(XElement node, string componentId, string fileId, TupleDefinitionType tableName) + private void ParseProductElement(XElement node) { var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - Identifier id = null; - var driver = fileId; - string name = null; - var setup = fileId; + var codepage = 65001; + string productCode = "*"; + string upgradeCode = null; + string manufacturer = null; + string version = null; + string symbols = null; + + this.activeName = null; + this.activeLanguage = null; foreach (var attrib in node.Attributes()) { @@ -41,18 +43,37 @@ namespace WixToolset.Core switch (attrib.Name.LocalName) { case "Id": - id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib); + productCode = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, true); break; - case "File": - driver = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); - this.Core.CreateSimpleReference(sourceLineNumbers, "File", driver); + case "Codepage": + codepage = this.Core.GetAttributeCodePageValue(sourceLineNumbers, attrib); + break; + case "Language": + this.activeLanguage = this.Core.GetAttributeLocalizableIntegerValue(sourceLineNumbers, attrib, 0, Int16.MaxValue); + break; + case "Manufacturer": + manufacturer = this.Core.GetAttributeValue(sourceLineNumbers, attrib, EmptyRule.MustHaveNonWhitespaceCharacters); + if ("PUT-COMPANY-NAME-HERE" == manufacturer) + { + this.Core.Write(WarningMessages.PlaceholderValue(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, manufacturer)); + } break; case "Name": - name = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + this.activeName = this.Core.GetAttributeValue(sourceLineNumbers, attrib, EmptyRule.MustHaveNonWhitespaceCharacters); + if ("PUT-PRODUCT-NAME-HERE" == this.activeName) + { + this.Core.Write(WarningMessages.PlaceholderValue(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, this.activeName)); + } break; - case "SetupFile": - setup = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); - this.Core.CreateSimpleReference(sourceLineNumbers, "File", setup); + case "UpgradeCode": + upgradeCode = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false); + break; + case "Version": // if the attribute is valid version, use the attribute value as is (so "1.0000.01.01" would *not* get translated to "1.0.1.1"). + var verifiedVersion = this.Core.GetAttributeVersionValue(sourceLineNumbers, attrib); + if (!String.IsNullOrEmpty(verifiedVersion)) + { + version = attrib.Value; + } break; default: this.Core.UnexpectedAttribute(node, attrib); @@ -65,32 +86,201 @@ namespace WixToolset.Core } } - if (null == name) + if (null == productCode) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); + } + + if (null == this.activeLanguage) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Language")); + } + + if (null == manufacturer) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Manufacturer")); + } + + if (null == this.activeName) { this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Name")); } - if (null == id) + if (null == upgradeCode) { - id = this.Core.CreateIdentifier("odb", name, fileId, setup); + this.Core.Write(WarningMessages.MissingUpgradeCode(sourceLineNumbers)); } - // drivers have a few possible children - if (TupleDefinitionType.ODBCDriver == tableName) + if (null == version) { - // process any data sources for the driver + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Version")); + } + else if (!CompilerCore.IsValidProductVersion(version)) + { + this.Core.Write(ErrorMessages.InvalidProductVersion(sourceLineNumbers, version)); + } + + if (this.Core.EncounteredError) + { + return; + } + + try + { + this.compilingProduct = true; + this.Core.CreateActiveSection(productCode, SectionType.Product, codepage, this.Context.CompilationId); + + this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Public, "Manufacturer"), manufacturer, false, false, false, true); + this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Public, "ProductCode"), productCode, false, false, false, true); + this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Public, "ProductLanguage"), this.activeLanguage, false, false, false, true); + this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Public, "ProductName"), this.activeName, false, false, false, true); + this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Public, "ProductVersion"), version, false, false, false, true); + if (null != upgradeCode) + { + this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Public, "UpgradeCode"), upgradeCode, false, false, false, true); + } + + var contextValues = new Dictionary + { + ["ProductLanguage"] = this.activeLanguage, + ["ProductVersion"] = version, + ["UpgradeCode"] = upgradeCode + }; + + var featureDisplay = 0; foreach (var child in node.Elements()) { if (CompilerCore.WixNamespace == child.Name.Namespace) { switch (child.Name.LocalName) { - case "ODBCDataSource": - string ignoredKeyPath = null; - this.ParseODBCDataSource(child, componentId, name, out ignoredKeyPath); + case "_locDefinition": + break; + case "AdminExecuteSequence": + this.ParseSequenceElement(child, SequenceTable.AdminExecuteSequence); + break; + case "AdminUISequence": + this.ParseSequenceElement(child, SequenceTable.AdminUISequence); + break; + case "AdvertiseExecuteSequence": + this.ParseSequenceElement(child, SequenceTable.AdvertiseExecuteSequence); + break; + case "InstallExecuteSequence": + this.ParseSequenceElement(child, SequenceTable.InstallExecuteSequence); + break; + case "InstallUISequence": + this.ParseSequenceElement(child, SequenceTable.InstallUISequence); + break; + case "AppId": + this.ParseAppIdElement(child, null, YesNoType.Yes, null, null, null); + break; + case "Binary": + this.ParseBinaryElement(child); + break; + case "ComplianceCheck": + this.ParseComplianceCheckElement(child); + break; + case "Component": + this.ParseComponentElement(child, ComplexReferenceParentType.Unknown, null, null, CompilerConstants.IntegerNotSet, null, null); + break; + case "ComponentGroup": + this.ParseComponentGroupElement(child, ComplexReferenceParentType.Unknown, null); + break; + case "Condition": + this.ParseConditionElement(child, node.Name.LocalName, null, null); + break; + case "CustomAction": + this.ParseCustomActionElement(child); + break; + case "CustomActionRef": + this.ParseSimpleRefElement(child, "CustomAction"); + break; + case "CustomTable": + this.ParseCustomTableElement(child); + break; + case "Directory": + this.ParseDirectoryElement(child, null, CompilerConstants.IntegerNotSet, String.Empty); + break; + case "DirectoryRef": + this.ParseDirectoryRefElement(child); + break; + case "EmbeddedChainer": + this.ParseEmbeddedChainerElement(child); + break; + case "EmbeddedChainerRef": + this.ParseSimpleRefElement(child, "MsiEmbeddedChainer"); + break; + case "EnsureTable": + this.ParseEnsureTableElement(child); + break; + case "Feature": + this.ParseFeatureElement(child, ComplexReferenceParentType.Product, productCode, ref featureDisplay); + break; + case "FeatureRef": + this.ParseFeatureRefElement(child, ComplexReferenceParentType.Product, productCode); + break; + case "FeatureGroupRef": + this.ParseFeatureGroupRefElement(child, ComplexReferenceParentType.Product, productCode); + break; + case "Icon": + this.ParseIconElement(child); + break; + case "InstanceTransforms": + this.ParseInstanceTransformsElement(child); + break; + case "MajorUpgrade": + this.ParseMajorUpgradeElement(child, contextValues); + break; + case "Media": + this.ParseMediaElement(child, null); + break; + case "MediaTemplate": + this.ParseMediaTemplateElement(child, null); + break; + case "Package": + this.ParsePackageElement(child, manufacturer, null); + break; + case "PackageCertificates": + case "PatchCertificates": + this.ParseCertificatesElement(child); break; case "Property": - this.ParseODBCProperty(child, id.Id, TupleDefinitionType.ODBCAttribute); + this.ParsePropertyElement(child); + break; + case "PropertyRef": + this.ParseSimpleRefElement(child, "Property"); + break; + case "SetDirectory": + this.ParseSetDirectoryElement(child); + break; + case "SetProperty": + this.ParseSetPropertyElement(child); + break; + case "SFPCatalog": + string parentName = null; + this.ParseSFPCatalogElement(child, ref parentName); + break; + case "SymbolPath": + if (null != symbols) + { + symbols += ";" + this.ParseSymbolPathElement(child); + } + else + { + symbols = this.ParseSymbolPathElement(child); + } + break; + case "UI": + this.ParseUIElement(child); + break; + case "UIRef": + this.ParseSimpleRefElement(child, "WixUI"); + break; + case "Upgrade": + this.ParseUpgradeElement(child); + break; + case "WixVariable": + this.ParseWixVariableElement(child); break; default: this.Core.UnexpectedElement(node, child); @@ -102,35 +292,140 @@ namespace WixToolset.Core this.Core.ParseExtensionElement(node, child); } } - } - else - { - this.Core.ParseForExtensionElements(node); - } - if (!this.Core.EncounteredError) + if (!this.Core.EncounteredError) + { + if (null != symbols) + { + var tuple = new WixDeltaPatchSymbolPathsTuple(sourceLineNumbers) + { + SymbolId = productCode, + SymbolType = SymbolPathType.Product, + SymbolPaths = symbols + }; + + this.Core.AddTuple(tuple); + } + } + } + finally { - var row = this.Core.CreateRow(sourceLineNumbers, tableName, id); - row.Set(1, componentId); - row.Set(2, name); - row.Set(3, driver); - row.Set(4, setup); + this.compilingProduct = false; } } /// - /// Parses a Property element underneath an ODBC driver or translator. + /// Parses an odbc driver or translator element. /// /// Element to parse. - /// Identifier of parent driver or translator. - /// Name of the table to create property in. - private void ParseODBCProperty(XElement node, string parentId, TupleDefinitionType tableName) + /// Identifier of parent component. + /// Default identifer for driver/translator file. + /// Tuple type we're processing for. + private void ParseODBCDriverOrTranslator(XElement node, string componentId, string fileId, TupleDefinitionType tupleDefinitionType) { var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - string id = null; - string propertyValue = null; - - foreach (var attrib in node.Attributes()) + Identifier id = null; + var driver = fileId; + string name = null; + var setup = fileId; + + foreach (var attrib in node.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib); + break; + case "File": + driver = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); + this.Core.CreateSimpleReference(sourceLineNumbers, "File", driver); + break; + case "Name": + name = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "SetupFile": + setup = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); + this.Core.CreateSimpleReference(sourceLineNumbers, "File", setup); + break; + default: + this.Core.UnexpectedAttribute(node, attrib); + break; + } + } + else + { + this.Core.ParseExtensionAttribute(node, attrib); + } + } + + if (null == name) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Name")); + } + + if (null == id) + { + id = this.Core.CreateIdentifier("odb", name, fileId, setup); + } + + // drivers have a few possible children + if (TupleDefinitionType.ODBCDriver == tupleDefinitionType) + { + // process any data sources for the driver + foreach (var child in node.Elements()) + { + if (CompilerCore.WixNamespace == child.Name.Namespace) + { + switch (child.Name.LocalName) + { + case "ODBCDataSource": + string ignoredKeyPath = null; + this.ParseODBCDataSource(child, componentId, name, out ignoredKeyPath); + break; + case "Property": + this.ParseODBCProperty(child, id.Id, TupleDefinitionType.ODBCAttribute); + break; + default: + this.Core.UnexpectedElement(node, child); + break; + } + } + else + { + this.Core.ParseExtensionElement(node, child); + } + } + } + else + { + this.Core.ParseForExtensionElements(node); + } + + if (!this.Core.EncounteredError) + { + var tuple = this.Core.CreateTuple(sourceLineNumbers, tupleDefinitionType, id); + tuple.Set(1, componentId); + tuple.Set(2, name); + tuple.Set(3, driver); + tuple.Set(4, setup); + } + } + + /// + /// Parses a Property element underneath an ODBC driver or translator. + /// + /// Element to parse. + /// Identifier of parent driver or translator. + /// Name of the table to create property in. + private void ParseODBCProperty(XElement node, string parentId, TupleDefinitionType tupleDefinitionType) + { + var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + string id = null; + string propertyValue = null; + + foreach (var attrib in node.Attributes()) { if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) { @@ -162,10 +457,10 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, tableName); - row.Set(0, parentId); - row.Set(1, id); - row.Set(2, propertyValue); + var tuple = this.Core.CreateTuple(sourceLineNumbers, tupleDefinitionType, new Identifier(AccessModifier.Private, parentId, id)); + tuple.Set(0, parentId); + tuple.Set(1, id); + tuple.Set(2, propertyValue); } } @@ -264,11 +559,13 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ODBCDataSource, id); - row.Set(1, componentId); - row.Set(2, name); - row.Set(3, driverName); - row.Set(4, registration); + this.Core.AddTuple(new ODBCDataSourceTuple(sourceLineNumbers, id) + { + Component_ = componentId, + Description = name, + DriverDescription = driverName, + Registration = registration + }); } possibleKeyPath = id.Id; @@ -296,7 +593,6 @@ namespace WixToolset.Core string platformValue = null; var security = YesNoDefaultType.Default; var sourceBits = (this.compilingModule ? 2 : 0); - IntermediateTuple row; var installPrivilegeSeen = false; var installScopeSeen = false; @@ -333,7 +629,7 @@ namespace WixToolset.Core case "AdminImage": if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) { - sourceBits = sourceBits | 4; + sourceBits |= 4; } break; case "Comments": @@ -348,7 +644,7 @@ namespace WixToolset.Core } else if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) { - sourceBits = sourceBits | 2; + sourceBits |= 2; } break; case "Description": @@ -363,7 +659,7 @@ namespace WixToolset.Core installPrivilegeSeen = true; break; case "limited": - sourceBits = sourceBits | 8; + sourceBits |= 8; installPrivilegeSeen = true; break; case "": @@ -379,13 +675,15 @@ namespace WixToolset.Core { case "perMachine": { - row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Property, new Identifier("ALLUSERS", AccessModifier.Public)); - row.Set(1, "1"); + this.Core.AddTuple(new PropertyTuple(sourceLineNumbers, new Identifier(AccessModifier.Public, "ALLUSERS")) + { + Value = "1" + }); installScopeSeen = true; } break; case "perUser": - sourceBits = sourceBits | 8; + sourceBits |= 8; installScopeSeen = true; break; case "": @@ -461,7 +759,7 @@ namespace WixToolset.Core case "ShortNames": if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) { - sourceBits = sourceBits | 1; + sourceBits |= 1; this.useShortFileNames = true; } break; @@ -534,81 +832,88 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); - row.Set(0, 1); - row.Set(1, codepage); + this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers) + { + PropertyId = SumaryInformationType.Codepage, + Value = codepage + }); - row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); - row.Set(0, 2); - row.Set(1, "Installation Database"); + this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers) + { + PropertyId = SumaryInformationType.Title, + Value = "Installation Database" + }); - row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); - row.Set(0, 3); - row.Set(1, packageName); + this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers) + { + PropertyId = SumaryInformationType.Subject, + Value = packageName + }); - row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); - row.Set(0, 4); - row.Set(1, packageAuthor); + this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers) + { + PropertyId = SumaryInformationType.Author, + Value = packageAuthor + }); - row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); - row.Set(0, 5); - row.Set(1, keywords); + this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers) + { + PropertyId = SumaryInformationType.Keywords, + Value = keywords + }); - row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); - row.Set(0, 6); - row.Set(1, comments); + this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers) + { + PropertyId = SumaryInformationType.Comments, + Value = comments + }); - row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); - row.Set(0, 7); - row.Set(1, String.Format(CultureInfo.InvariantCulture, "{0};{1}", platform, packageLanguages)); + this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers) + { + PropertyId = SumaryInformationType.PlatformAndLanguage, + Value = String.Format(CultureInfo.InvariantCulture, "{0};{1}", platform, packageLanguages) + }); - row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); - row.Set(0, 9); - row.Set(1, packageCode); + this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers) + { + PropertyId = SumaryInformationType.PackageCode, + Value = packageCode + }); - row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); - row.Set(0, 14); - row.Set(1, msiVersion.ToString(CultureInfo.InvariantCulture)); + this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers) + { + PropertyId = SumaryInformationType.WindowsInstallerVersion, + Value = msiVersion.ToString(CultureInfo.InvariantCulture) + }); - row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); - row.Set(0, 15); - row.Set(1, sourceBits.ToString(CultureInfo.InvariantCulture)); + this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers) + { + PropertyId = SumaryInformationType.WordCount, + Value = sourceBits.ToString(CultureInfo.InvariantCulture) + }); - row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); - row.Set(0, 19); - switch (security) + this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers) { - case YesNoDefaultType.No: // no restriction - row.Set(1, "0"); - break; - case YesNoDefaultType.Default: // read-only recommended - row.Set(1, "2"); - break; - case YesNoDefaultType.Yes: // read-only enforced - row.Set(1, "4"); - break; - } + PropertyId = SumaryInformationType.Security, + Value = YesNoDefaultType.No == security ? "0" : YesNoDefaultType.Yes == security ? "4" : "2" + }); } } /// - /// Parses a patch metadata element. + /// Parses a patch information element. /// /// Element to parse. - private void ParsePatchMetadataElement(XElement node) + private void ParsePatchInformationElement(XElement node) { var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - var allowRemoval = YesNoType.NotSet; - string classification = null; - string creationTimeUtc = null; - string description = null; - string displayName = null; - string manufacturerName = null; - string minorUpdateTargetRTM = null; - string moreInfoUrl = null; - var optimizeCA = CompilerConstants.IntegerNotSet; - var optimizedInstallMode = YesNoType.NotSet; - string targetProductName = null; + var codepage = "1252"; + string comments = null; + var keywords = "Installer,Patching,PCP,Database"; + var msiVersion = 1; // Should always be 1 for patches + string packageAuthor = null; + var packageName = this.activeName; + var security = YesNoDefaultType.Default; foreach (var attrib in node.Attributes()) { @@ -616,35 +921,38 @@ namespace WixToolset.Core { switch (attrib.Name.LocalName) { - case "AllowRemoval": - allowRemoval = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + case "AdminImage": + this.Core.Write(WarningMessages.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); break; - case "Classification": - classification = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + case "Comments": + comments = this.Core.GetAttributeValue(sourceLineNumbers, attrib); break; - case "CreationTimeUTC": - creationTimeUtc = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + case "Compressed": + this.Core.Write(WarningMessages.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); break; case "Description": - description = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + packageName = this.Core.GetAttributeValue(sourceLineNumbers, attrib); break; - case "DisplayName": - displayName = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + case "Keywords": + keywords = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Languages": + this.Core.Write(WarningMessages.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); break; - case "ManufacturerName": - manufacturerName = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + case "Manufacturer": + packageAuthor = this.Core.GetAttributeValue(sourceLineNumbers, attrib); break; - case "MinorUpdateTargetRTM": - minorUpdateTargetRTM = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + case "Platforms": + this.Core.Write(WarningMessages.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); break; - case "MoreInfoURL": - moreInfoUrl = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + case "ReadOnly": + security = this.Core.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib); break; - case "OptimizedInstallMode": - optimizedInstallMode = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + case "ShortNames": + this.Core.Write(WarningMessages.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); break; - case "TargetProductName": - targetProductName = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + case "SummaryCodepage": + codepage = this.Core.GetAttributeLocalizableCodePageValue(sourceLineNumbers, attrib); break; default: this.Core.UnexpectedAttribute(node, attrib); @@ -657,425 +965,114 @@ namespace WixToolset.Core } } - if (YesNoType.NotSet == allowRemoval) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "AllowRemoval")); - } - - if (null == classification) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Classification")); - } - - if (null == description) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Description")); - } - - if (null == displayName) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "DisplayName")); - } - - if (null == manufacturerName) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "ManufacturerName")); - } - - if (null == moreInfoUrl) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "MoreInfoURL")); - } - - if (null == targetProductName) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "TargetProductName")); - } - - foreach (var child in node.Elements()) - { - if (CompilerCore.WixNamespace == child.Name.Namespace) - { - switch (child.Name.LocalName) - { - case "CustomProperty": - this.ParseCustomPropertyElement(child); - break; - case "OptimizeCustomActions": - optimizeCA = this.ParseOptimizeCustomActionsElement(child); - break; - default: - this.Core.UnexpectedElement(node, child); - break; - } - } - else - { - this.Core.ParseExtensionElement(node, child); - } - } + this.Core.ParseForExtensionElements(node); if (!this.Core.EncounteredError) { - if (YesNoType.NotSet != allowRemoval) + this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PatchMetadata); - row.Set(1, "AllowRemoval"); - row.Set(2, YesNoType.Yes == allowRemoval ? "1" : "0"); - } - - if (null != classification) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PatchMetadata); - row.Set(1, "Classification"); - row.Set(2, classification); - } + PropertyId = SumaryInformationType.Codepage, + Value = codepage + }); - if (null != creationTimeUtc) + this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PatchMetadata); - row.Set(1, "CreationTimeUTC"); - row.Set(2, creationTimeUtc); - } + PropertyId = SumaryInformationType.Title, + Value = "Patch" + }); - if (null != description) + if (null != packageName) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PatchMetadata); - row.Set(1, "Description"); - row.Set(2, description); + this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers) + { + PropertyId = SumaryInformationType.Subject, + Value = packageName + }); } - if (null != displayName) + if (null != packageAuthor) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PatchMetadata); - row.Set(1, "DisplayName"); - row.Set(2, displayName); + this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers) + { + PropertyId = SumaryInformationType.Author, + Value = packageAuthor + }); } - if (null != manufacturerName) + if (null != keywords) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PatchMetadata); - row.Set(1, "ManufacturerName"); - row.Set(2, manufacturerName); + this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers) + { + PropertyId = SumaryInformationType.Keywords, + Value = keywords + }); } - if (null != minorUpdateTargetRTM) + if (null != comments) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PatchMetadata); - row.Set(1, "MinorUpdateTargetRTM"); - row.Set(2, minorUpdateTargetRTM); + this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers) + { + PropertyId = SumaryInformationType.Comments, + Value = comments + }); } - if (null != moreInfoUrl) + this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PatchMetadata); - row.Set(1, "MoreInfoURL"); - row.Set(2, moreInfoUrl); - } + PropertyId = SumaryInformationType.WindowsInstallerVersion, + Value = msiVersion.ToString(CultureInfo.InvariantCulture) + }); - if (CompilerConstants.IntegerNotSet != optimizeCA) + this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PatchMetadata); - row.Set(1, "OptimizeCA"); - row.Set(2, optimizeCA.ToString(CultureInfo.InvariantCulture)); - } + PropertyId = SumaryInformationType.WordCount, + Value = "0" + }); - if (YesNoType.NotSet != optimizedInstallMode) + this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PatchMetadata); - row.Set(1, "OptimizedInstallMode"); - row.Set(2, YesNoType.Yes == optimizedInstallMode ? "1" : "0"); - } + PropertyId = SumaryInformationType.WindowsInstallerVersion, + Value = msiVersion.ToString(CultureInfo.InvariantCulture) + }); - if (null != targetProductName) + this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PatchMetadata); - row.Set(1, "TargetProductName"); - row.Set(2, targetProductName); - } + PropertyId = SumaryInformationType.Security, + Value = YesNoDefaultType.No == security ? "0" : YesNoDefaultType.Yes == security ? "4" : "2" + }); } } /// - /// Parses a custom property element for the PatchMetadata table. + /// Parses a permission element. /// /// Element to parse. - private void ParseCustomPropertyElement(XElement node) + /// Identifier of object to be secured. + /// Name of table that contains objectId. + private void ParsePermissionElement(XElement node, string objectId, string tableName) { var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - string company = null; - string property = null; - string value = null; - - foreach (var attrib in node.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Company": - company = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Property": - property = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Value": - value = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - default: - this.Core.UnexpectedAttribute(node, attrib); - break; - } - } - else - { - this.Core.ParseExtensionAttribute(node, attrib); - } - } - - if (null == company) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Company")); - } - - if (null == property) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Property")); - } - - if (null == value) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Value")); - } - - this.Core.ParseForExtensionElements(node); - - if (!this.Core.EncounteredError) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PatchMetadata); - row.Set(0, company); - row.Set(1, property); - row.Set(2, value); - } - } - - /// - /// Parses the OptimizeCustomActions element. - /// - /// Element to parse. - /// The combined integer value for callers to store as appropriate. - private int ParseOptimizeCustomActionsElement(XElement node) - { - var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - var optimizeCA = OptimizeCA.None; - - foreach (var attrib in node.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "SkipAssignment": - if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - optimizeCA |= OptimizeCA.SkipAssignment; - } - break; - case "SkipImmediate": - if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - optimizeCA |= OptimizeCA.SkipImmediate; - } - break; - case "SkipDeferred": - if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) - { - optimizeCA |= OptimizeCA.SkipDeferred; - } - break; - default: - this.Core.UnexpectedAttribute(node, attrib); - break; - } - } - else - { - this.Core.ParseExtensionAttribute(node, attrib); - } - } - - return (int)optimizeCA; - } - - /// - /// Parses a patch information element. - /// - /// Element to parse. - private void ParsePatchInformationElement(XElement node) - { - var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - var codepage = "1252"; - string comments = null; - var keywords = "Installer,Patching,PCP,Database"; - var msiVersion = 1; // Should always be 1 for patches - string packageAuthor = null; - var packageName = this.activeName; - var security = YesNoDefaultType.Default; - - foreach (var attrib in node.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "AdminImage": - this.Core.Write(WarningMessages.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); - break; - case "Comments": - comments = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Compressed": - this.Core.Write(WarningMessages.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); - break; - case "Description": - packageName = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Keywords": - keywords = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Languages": - this.Core.Write(WarningMessages.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); - break; - case "Manufacturer": - packageAuthor = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "Platforms": - this.Core.Write(WarningMessages.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); - break; - case "ReadOnly": - security = this.Core.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib); - break; - case "ShortNames": - this.Core.Write(WarningMessages.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); - break; - case "SummaryCodepage": - codepage = this.Core.GetAttributeLocalizableCodePageValue(sourceLineNumbers, attrib); - break; - default: - this.Core.UnexpectedAttribute(node, attrib); - break; - } - } - else - { - this.Core.ParseExtensionAttribute(node, attrib); - } - } - - this.Core.ParseForExtensionElements(node); - - if (!this.Core.EncounteredError) - { - // PID_CODEPAGE - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); - row.Set(0, 1); - row.Set(1, codepage); - - // PID_TITLE - row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); - row.Set(0, 2); - row.Set(1, "Patch"); - - // PID_SUBJECT - if (null != packageName) - { - row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); - row.Set(0, 3); - row.Set(1, packageName); - } - - // PID_AUTHOR - if (null != packageAuthor) - { - row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); - row.Set(0, 4); - row.Set(1, packageAuthor); - } - - // PID_KEYWORDS - if (null != keywords) - { - row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); - row.Set(0, 5); - row.Set(1, keywords); - } - - // PID_COMMENTS - if (null != comments) - { - row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); - row.Set(0, 6); - row.Set(1, comments); - } - - // PID_PAGECOUNT - row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); - row.Set(0, 14); - row.Set(1, msiVersion.ToString(CultureInfo.InvariantCulture)); - - // PID_WORDCOUNT - row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); - row.Set(0, 15); - row.Set(1, "0"); - - // PID_SECURITY - row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); - row.Set(0, 19); - switch (security) - { - case YesNoDefaultType.No: // no restriction - row.Set(1, "0"); - break; - case YesNoDefaultType.Default: // read-only recommended - row.Set(1, "2"); - break; - case YesNoDefaultType.Yes: // read-only enforced - row.Set(1, "4"); - break; - } - } - } - - /// - /// Parses a permission element. - /// - /// Element to parse. - /// Identifier of object to be secured. - /// Name of table that contains objectId. - private void ParsePermissionElement(XElement node, string objectId, string tableName) - { - var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - var bits = new BitArray(32); - string domain = null; - var permission = 0; - string[] specialPermissions = null; - string user = null; - - switch (tableName) - { - case "CreateFolder": - specialPermissions = Common.FolderPermissions; - break; - case "File": - specialPermissions = Common.FilePermissions; - break; - case "Registry": - specialPermissions = Common.RegistryPermissions; - break; - default: - this.Core.UnexpectedElement(node.Parent, node); - return; // stop processing this element since no valid permissions are available - } + var bits = new BitArray(32); + string domain = null; + var permission = 0; + string[] specialPermissions = null; + string user = null; + + switch (tableName) + { + case "CreateFolder": + specialPermissions = Common.FolderPermissions; + break; + case "File": + specialPermissions = Common.FilePermissions; + break; + case "Registry": + specialPermissions = Common.RegistryPermissions; + break; + default: + this.Core.UnexpectedElement(node.Parent, node); + return; // stop processing this element since no valid permissions are available + } foreach (var attrib in node.Attributes()) { @@ -1085,440 +1082,160 @@ namespace WixToolset.Core { case "Domain": domain = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "User": - user = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - case "FileAllRights": - // match the WinNT.h mask FILE_ALL_ACCESS for value 0x001F01FF (aka 1 1111 0000 0001 1111 1111 or 2032127) - bits[0] = bits[1] = bits[2] = bits[3] = bits[4] = bits[5] = bits[6] = bits[7] = bits[8] = bits[16] = bits[17] = bits[18] = bits[19] = bits[20] = true; - break; - case "SpecificRightsAll": - // match the WinNT.h mask SPECIFIC_RIGHTS_ALL for value 0x0000FFFF (aka 1111 1111 1111 1111) - bits[0] = bits[1] = bits[2] = bits[3] = bits[4] = bits[5] = bits[6] = bits[7] = bits[8] = bits[9] = bits[10] = bits[11] = bits[12] = bits[13] = bits[14] = bits[15] = true; - break; - default: - var attribValue = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); - if (!this.Core.TrySetBitFromName(Common.StandardPermissions, attrib.Name.LocalName, attribValue, bits, 16)) - { - if (!this.Core.TrySetBitFromName(Common.GenericPermissions, attrib.Name.LocalName, attribValue, bits, 28)) - { - if (!this.Core.TrySetBitFromName(specialPermissions, attrib.Name.LocalName, attribValue, bits, 0)) - { - this.Core.UnexpectedAttribute(node, attrib); - break; - } - } - } - break; - } - } - else - { - this.Core.ParseExtensionAttribute(node, attrib); - } - } - - permission = this.Core.CreateIntegerFromBitArray(bits); - - if (null == user) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "User")); - } - - if (Int32.MinValue == permission) // just GENERIC_READ, which is MSI_NULL - { - this.Core.Write(ErrorMessages.GenericReadNotAllowed(sourceLineNumbers)); - } - - this.Core.ParseForExtensionElements(node); - - if (!this.Core.EncounteredError) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.LockPermissions); - row.Set(0, objectId); - row.Set(1, tableName); - row.Set(2, domain); - row.Set(3, user); - row.Set(4, permission); - } - } - - /// - /// Parses an extended permission element. - /// - /// Element to parse. - /// Identifier of object to be secured. - /// Name of table that contains objectId. - private void ParsePermissionExElement(XElement node, string objectId, string tableName) - { - var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - string condition = null; - Identifier id = null; - string sddl = null; - - switch (tableName) - { - case "CreateFolder": - case "File": - case "Registry": - case "ServiceInstall": - break; - default: - this.Core.UnexpectedElement(node.Parent, node); - return; // stop processing this element since nothing will be valid. - } - - foreach (var attrib in node.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Id": - id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib); - break; - case "Sddl": - sddl = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - break; - default: - this.Core.UnexpectedAttribute(node, attrib); - break; - } - } - else - { - this.Core.ParseExtensionAttribute(node, attrib); - } - } - - if (null == sddl) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Sddl")); - } - - if (null == id) - { - id = this.Core.CreateIdentifier("pme", objectId, tableName, sddl); - } - - foreach (var child in node.Elements()) - { - if (CompilerCore.WixNamespace == child.Name.Namespace) - { - switch (child.Name.LocalName) - { - case "Condition": - if (null != condition) - { - var childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - this.Core.Write(ErrorMessages.TooManyChildren(childSourceLineNumbers, node.Name.LocalName, child.Name.LocalName)); - } - - condition = this.ParseConditionElement(child, node.Name.LocalName, null, null); - break; - default: - this.Core.UnexpectedElement(node, child); - break; - } - } - else - { - this.Core.ParseExtensionElement(node, child); - } - } - - if (!this.Core.EncounteredError) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiLockPermissionsEx, id); - row.Set(1, objectId); - row.Set(2, tableName); - row.Set(3, sddl); - row.Set(4, condition); - } - } - - /// - /// Parses a product element. - /// - /// Element to parse. - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")] - private void ParseProductElement(XElement node) - { - var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - var codepage = 65001; - string productCode = "*"; - string upgradeCode = null; - string manufacturer = null; - string version = null; - string symbols = null; - - this.activeName = null; - this.activeLanguage = null; - - foreach (var attrib in node.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "Id": - productCode = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, true); - break; - case "Codepage": - codepage = this.Core.GetAttributeCodePageValue(sourceLineNumbers, attrib); - break; - case "Language": - this.activeLanguage = this.Core.GetAttributeLocalizableIntegerValue(sourceLineNumbers, attrib, 0, Int16.MaxValue); - break; - case "Manufacturer": - manufacturer = this.Core.GetAttributeValue(sourceLineNumbers, attrib, EmptyRule.MustHaveNonWhitespaceCharacters); - if ("PUT-COMPANY-NAME-HERE" == manufacturer) - { - this.Core.Write(WarningMessages.PlaceholderValue(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, manufacturer)); - } - break; - case "Name": - this.activeName = this.Core.GetAttributeValue(sourceLineNumbers, attrib, EmptyRule.MustHaveNonWhitespaceCharacters); - if ("PUT-PRODUCT-NAME-HERE" == this.activeName) - { - this.Core.Write(WarningMessages.PlaceholderValue(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, this.activeName)); - } - break; - case "UpgradeCode": - upgradeCode = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false); - break; - case "Version": // if the attribute is valid version, use the attribute value as is (so "1.0000.01.01" would *not* get translated to "1.0.1.1"). - var verifiedVersion = this.Core.GetAttributeVersionValue(sourceLineNumbers, attrib); - if (!String.IsNullOrEmpty(verifiedVersion)) - { - version = attrib.Value; - } - break; - default: - this.Core.UnexpectedAttribute(node, attrib); - break; - } - } - else - { - this.Core.ParseExtensionAttribute(node, attrib); - } - } - - if (null == productCode) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); - } - - if (null == this.activeLanguage) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Language")); - } - - if (null == manufacturer) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Manufacturer")); - } - - if (null == this.activeName) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Name")); - } - - if (null == upgradeCode) - { - this.Core.Write(WarningMessages.MissingUpgradeCode(sourceLineNumbers)); - } - - if (null == version) - { - this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Version")); - } - else if (!CompilerCore.IsValidProductVersion(version)) - { - this.Core.Write(ErrorMessages.InvalidProductVersion(sourceLineNumbers, version)); - } - - if (this.Core.EncounteredError) - { - return; - } - - try - { - this.compilingProduct = true; - this.Core.CreateActiveSection(productCode, SectionType.Product, codepage, this.Context.CompilationId); - - this.AddProperty(sourceLineNumbers, new Identifier("Manufacturer", AccessModifier.Public), manufacturer, false, false, false, true); - this.AddProperty(sourceLineNumbers, new Identifier("ProductCode", AccessModifier.Public), productCode, false, false, false, true); - this.AddProperty(sourceLineNumbers, new Identifier("ProductLanguage", AccessModifier.Public), this.activeLanguage, false, false, false, true); - this.AddProperty(sourceLineNumbers, new Identifier("ProductName", AccessModifier.Public), this.activeName, false, false, false, true); - this.AddProperty(sourceLineNumbers, new Identifier("ProductVersion", AccessModifier.Public), version, false, false, false, true); - if (null != upgradeCode) - { - this.AddProperty(sourceLineNumbers, new Identifier("UpgradeCode", AccessModifier.Public), upgradeCode, false, false, false, true); - } - - var contextValues = new Dictionary - { - ["ProductLanguage"] = this.activeLanguage, - ["ProductVersion"] = version, - ["UpgradeCode"] = upgradeCode - }; - - var featureDisplay = 0; - foreach (var child in node.Elements()) - { - if (CompilerCore.WixNamespace == child.Name.Namespace) - { - switch (child.Name.LocalName) - { - case "_locDefinition": - break; - case "AdminExecuteSequence": - case "AdminUISequence": - case "AdvertiseExecuteSequence": - case "InstallExecuteSequence": - case "InstallUISequence": - this.ParseSequenceElement(child, child.Name.LocalName); - break; - case "AppId": - this.ParseAppIdElement(child, null, YesNoType.Yes, null, null, null); - break; - case "Binary": - this.ParseBinaryElement(child); - break; - case "ComplianceCheck": - this.ParseComplianceCheckElement(child); - break; - case "Component": - this.ParseComponentElement(child, ComplexReferenceParentType.Unknown, null, null, CompilerConstants.IntegerNotSet, null, null); - break; - case "ComponentGroup": - this.ParseComponentGroupElement(child, ComplexReferenceParentType.Unknown, null); - break; - case "Condition": - this.ParseConditionElement(child, node.Name.LocalName, null, null); - break; - case "CustomAction": - this.ParseCustomActionElement(child); - break; - case "CustomActionRef": - this.ParseSimpleRefElement(child, "CustomAction"); - break; - case "CustomTable": - this.ParseCustomTableElement(child); - break; - case "Directory": - this.ParseDirectoryElement(child, null, CompilerConstants.IntegerNotSet, String.Empty); - break; - case "DirectoryRef": - this.ParseDirectoryRefElement(child); - break; - case "EmbeddedChainer": - this.ParseEmbeddedChainerElement(child); - break; - case "EmbeddedChainerRef": - this.ParseSimpleRefElement(child, "MsiEmbeddedChainer"); - break; - case "EnsureTable": - this.ParseEnsureTableElement(child); - break; - case "Feature": - this.ParseFeatureElement(child, ComplexReferenceParentType.Product, productCode, ref featureDisplay); - break; - case "FeatureRef": - this.ParseFeatureRefElement(child, ComplexReferenceParentType.Product, productCode); - break; - case "FeatureGroupRef": - this.ParseFeatureGroupRefElement(child, ComplexReferenceParentType.Product, productCode); - break; - case "Icon": - this.ParseIconElement(child); - break; - case "InstanceTransforms": - this.ParseInstanceTransformsElement(child); - break; - case "MajorUpgrade": - this.ParseMajorUpgradeElement(child, contextValues); - break; - case "Media": - this.ParseMediaElement(child, null); - break; - case "MediaTemplate": - this.ParseMediaTemplateElement(child, null); - break; - case "Package": - this.ParsePackageElement(child, manufacturer, null); - break; - case "PackageCertificates": - case "PatchCertificates": - this.ParseCertificatesElement(child); - break; - case "Property": - this.ParsePropertyElement(child); - break; - case "PropertyRef": - this.ParseSimpleRefElement(child, "Property"); - break; - case "SetDirectory": - this.ParseSetDirectoryElement(child); - break; - case "SetProperty": - this.ParseSetPropertyElement(child); - break; - case "SFPCatalog": - string parentName = null; - this.ParseSFPCatalogElement(child, ref parentName); - break; - case "SymbolPath": - if (null != symbols) - { - symbols += ";" + this.ParseSymbolPathElement(child); - } - else + break; + case "User": + user = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "FileAllRights": + // match the WinNT.h mask FILE_ALL_ACCESS for value 0x001F01FF (aka 1 1111 0000 0001 1111 1111 or 2032127) + bits[0] = bits[1] = bits[2] = bits[3] = bits[4] = bits[5] = bits[6] = bits[7] = bits[8] = bits[16] = bits[17] = bits[18] = bits[19] = bits[20] = true; + break; + case "SpecificRightsAll": + // match the WinNT.h mask SPECIFIC_RIGHTS_ALL for value 0x0000FFFF (aka 1111 1111 1111 1111) + bits[0] = bits[1] = bits[2] = bits[3] = bits[4] = bits[5] = bits[6] = bits[7] = bits[8] = bits[9] = bits[10] = bits[11] = bits[12] = bits[13] = bits[14] = bits[15] = true; + break; + default: + var attribValue = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + if (!this.Core.TrySetBitFromName(Common.StandardPermissions, attrib.Name.LocalName, attribValue, bits, 16)) + { + if (!this.Core.TrySetBitFromName(Common.GenericPermissions, attrib.Name.LocalName, attribValue, bits, 28)) { - symbols = this.ParseSymbolPathElement(child); + if (!this.Core.TrySetBitFromName(specialPermissions, attrib.Name.LocalName, attribValue, bits, 0)) + { + this.Core.UnexpectedAttribute(node, attrib); + break; + } } - break; - case "UI": - this.ParseUIElement(child); - break; - case "UIRef": - this.ParseSimpleRefElement(child, "WixUI"); - break; - case "Upgrade": - this.ParseUpgradeElement(child); - break; - case "WixVariable": - this.ParseWixVariableElement(child); - break; - default: - this.Core.UnexpectedElement(node, child); - break; } + break; } - else + } + else + { + this.Core.ParseExtensionAttribute(node, attrib); + } + } + + permission = this.Core.CreateIntegerFromBitArray(bits); + + if (null == user) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "User")); + } + + if (Int32.MinValue == permission) // just GENERIC_READ, which is MSI_NULL + { + this.Core.Write(ErrorMessages.GenericReadNotAllowed(sourceLineNumbers)); + } + + this.Core.ParseForExtensionElements(node); + + if (!this.Core.EncounteredError) + { + this.Core.AddTuple(new LockPermissionsTuple(sourceLineNumbers) + { + LockObject = objectId, + Table = tableName, + Domain = domain, + User = user, + Permission = permission + }); + } + } + + /// + /// Parses an extended permission element. + /// + /// Element to parse. + /// Identifier of object to be secured. + /// Name of table that contains objectId. + private void ParsePermissionExElement(XElement node, string objectId, string tableName) + { + var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + string condition = null; + Identifier id = null; + string sddl = null; + + switch (tableName) + { + case "CreateFolder": + case "File": + case "Registry": + case "ServiceInstall": + break; + default: + this.Core.UnexpectedElement(node.Parent, node); + return; // stop processing this element since nothing will be valid. + } + + foreach (var attrib in node.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) { - this.Core.ParseExtensionElement(node, child); + case "Id": + id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib); + break; + case "Sddl": + sddl = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + default: + this.Core.UnexpectedAttribute(node, attrib); + break; } } + else + { + this.Core.ParseExtensionAttribute(node, attrib); + } + } - if (!this.Core.EncounteredError) + if (null == sddl) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Sddl")); + } + + if (null == id) + { + id = this.Core.CreateIdentifier("pme", objectId, tableName, sddl); + } + + foreach (var child in node.Elements()) + { + if (CompilerCore.WixNamespace == child.Name.Namespace) { - if (null != symbols) + switch (child.Name.LocalName) { - var symbolRow = (WixDeltaPatchSymbolPathsTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixDeltaPatchSymbolPaths); - symbolRow.Id = productCode; - symbolRow.Type = SymbolPathType.Product; - symbolRow.SymbolPaths = symbols; + case "Condition": + if (null != condition) + { + var childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + this.Core.Write(ErrorMessages.TooManyChildren(childSourceLineNumbers, node.Name.LocalName, child.Name.LocalName)); + } + + condition = this.ParseConditionElement(child, node.Name.LocalName, null, null); + break; + default: + this.Core.UnexpectedElement(node, child); + break; } } + else + { + this.Core.ParseExtensionElement(node, child); + } } - finally + + if (!this.Core.EncounteredError) { - this.compilingProduct = false; + this.Core.AddTuple(new MsiLockPermissionsExTuple(sourceLineNumbers, id) + { + LockObject = objectId, + Table = tableName, + SDDLText =sddl, + Condition = condition + }); } } @@ -1644,22 +1361,27 @@ namespace WixToolset.Core { if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ProgId); - row.Set(0, progId); - row.Set(1, parent); - row.Set(2, classId); - row.Set(3, description); + var tuple = new ProgIdTuple(sourceLineNumbers, new Identifier(AccessModifier.Public, progId)) + { + ProgId = progId, + ProgId_Parent = parent, + Class_ = classId, + Description = description, + }; + if (null != icon) { - row.Set(4, icon); + tuple.Icon_ = icon; this.Core.CreateSimpleReference(sourceLineNumbers, "Icon", icon); } if (CompilerConstants.IntegerNotSet != iconIndex) { - row.Set(5, iconIndex); + tuple.IconIndex = iconIndex; } + this.Core.AddTuple(tuple); + this.Core.EnsureTable(sourceLineNumbers, "Class"); } } @@ -1834,7 +1556,7 @@ namespace WixToolset.Core { if (complianceCheck && !this.Core.EncounteredError) { - this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.CCPSearch, new Identifier(sig, AccessModifier.Private)); + this.Core.AddTuple(new CCPSearchTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, sig))); } this.AddAppSearch(sourceLineNumbers, id, sig); @@ -1863,7 +1585,7 @@ namespace WixToolset.Core { this.Core.Write(WarningMessages.PropertyModularizationSuppressed(sourceLineNumbers)); - this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixSuppressModularization, id); + this.Core.AddTuple(new WixSuppressModularizationTuple(sourceLineNumbers, id)); } } @@ -2521,7 +2243,8 @@ namespace WixToolset.Core Identifier id = null; string directory = null; string name = null; - var on = CompilerConstants.IntegerNotSet; + bool? onInstall = null; + bool? onUninstall = null; string property = null; string shortName = null; @@ -2545,16 +2268,14 @@ namespace WixToolset.Core switch (onValue) { case "install": - on = 1; + onInstall = true; break; case "uninstall": - on = 2; + onUninstall = true; break; case "both": - on = 3; - break; - default: - on = CompilerConstants.IllegalInteger; + onInstall = true; + onUninstall = true; break; } break; @@ -2599,10 +2320,9 @@ namespace WixToolset.Core } } - if (CompilerConstants.IntegerNotSet == on) + if (!onInstall.HasValue && !onUninstall.HasValue) { this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "On")); - on = CompilerConstants.IllegalInteger; } if (null != directory && null != property) @@ -2612,6 +2332,7 @@ namespace WixToolset.Core if (null == id) { + var on = (onInstall == true && onUninstall == true) ? 3 : (onUninstall == true) ? 2 : (onInstall == true) ? 1 : 0; id = this.Core.CreateIdentifier("rmf", directory ?? property ?? parentDirectory, LowercaseOrNull(shortName), LowercaseOrNull(name), on.ToString()); } @@ -2619,22 +2340,16 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.RemoveFile, id); - row.Set(1, componentId); - row.Set(2, this.GetMsiFilenameValue(shortName, name)); - if (null != directory) - { - row.Set(3, directory); - } - else if (null != property) - { - row.Set(3, property); - } - else + var tuple = new RemoveFileTuple(sourceLineNumbers, id) { - row.Set(3, parentDirectory); - } - row.Set(4, on); + Component_ = componentId, + FileName = this.GetMsiFilenameValue(shortName, name), + DirProperty = directory ?? property ?? parentDirectory, + OnInstall = onInstall, + OnUninstall = onUninstall + }; + + this.Core.AddTuple(tuple); } } @@ -2649,7 +2364,8 @@ namespace WixToolset.Core var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); Identifier id = null; string directory = null; - var on = CompilerConstants.IntegerNotSet; + bool? onInstall = null; + bool? onUninstall = null; string property = null; foreach (var attrib in node.Attributes()) @@ -2669,16 +2385,14 @@ namespace WixToolset.Core switch (onValue) { case "install": - on = 1; + onInstall = true; break; case "uninstall": - on = 2; + onUninstall = true; break; case "both": - on = 3; - break; - default: - on = CompilerConstants.IllegalInteger; + onInstall = true; + onUninstall = true; break; } break; @@ -2696,10 +2410,9 @@ namespace WixToolset.Core } } - if (CompilerConstants.IntegerNotSet == on) + if (!onInstall.HasValue && !onUninstall.HasValue) { this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "On")); - on = CompilerConstants.IllegalInteger; } if (null != directory && null != property) @@ -2709,6 +2422,7 @@ namespace WixToolset.Core if (null == id) { + var on = (onInstall == true && onUninstall == true) ? 3 : (onUninstall == true) ? 2 : (onInstall == true) ? 1 : 0; id = this.Core.CreateIdentifier("rmf", directory ?? property ?? parentDirectory, on.ToString()); } @@ -2716,22 +2430,15 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.RemoveFile, id); - row.Set(1, componentId); - //row.Set(2, null); - if (null != directory) - { - row.Set(3, directory); - } - else if (null != property) - { - row.Set(3, property); - } - else + var tuple = new RemoveFileTuple(sourceLineNumbers, id) { - row.Set(3, parentDirectory); - } - row.Set(4, on); + Component_ = componentId, + DirProperty = directory ?? property ?? parentDirectory, + OnInstall = onInstall, + OnUninstall = onUninstall + }; + + this.Core.AddTuple(tuple); } } @@ -2796,11 +2503,13 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ReserveCost, id); - row.Set(1, componentId); - row.Set(2, directoryId); - row.Set(3, runLocal); - row.Set(4, runFromSource); + this.Core.AddTuple(new ReserveCostTuple(sourceLineNumbers, id) + { + Component_ = componentId, + ReserveFolder = directoryId, + ReserveLocal = runLocal, + ReserveSource = runFromSource + }); } } @@ -2809,14 +2518,8 @@ namespace WixToolset.Core /// /// Element to parse. /// Name of sequence table. - private void ParseSequenceElement(XElement node, string sequenceTable) + private void ParseSequenceElement(XElement node, SequenceTable sequenceTable) { - // use the proper table name internally - if ("AdvertiseExecuteSequence" == sequenceTable) - { - sequenceTable = "AdvtExecuteSequence"; - } - // Parse each action in the sequence. foreach (var child in node.Elements()) { @@ -2855,7 +2558,7 @@ namespace WixToolset.Core if (customAction || showDialog || specialAction || specialStandardAction) { afterAction = this.Core.GetAttributeIdentifierValue(childSourceLineNumbers, attrib); - this.Core.CreateSimpleReference(childSourceLineNumbers, "WixAction", sequenceTable, afterAction); + this.Core.CreateSimpleReference(childSourceLineNumbers, "WixAction", sequenceTable.ToString(), afterAction); } else { @@ -2866,7 +2569,7 @@ namespace WixToolset.Core if (customAction || showDialog || specialAction || specialStandardAction) { beforeAction = this.Core.GetAttributeIdentifierValue(childSourceLineNumbers, attrib); - this.Core.CreateSimpleReference(childSourceLineNumbers, "WixAction", sequenceTable, beforeAction); + this.Core.CreateSimpleReference(childSourceLineNumbers, "WixAction", sequenceTable.ToString(), beforeAction); } else { @@ -2995,23 +2698,30 @@ namespace WixToolset.Core { if (suppress) { - var row = this.Core.CreateRow(childSourceLineNumbers, TupleDefinitionType.WixSuppressAction, new Identifier(AccessModifier.Public, sequenceTable, actionName)); - row.Set(0, sequenceTable); - row.Set(1, actionName); + this.Core.AddTuple(new WixSuppressActionTuple(childSourceLineNumbers, new Identifier(AccessModifier.Public, sequenceTable, actionName)) + { + SequenceTable = sequenceTable, + Action = actionName + }); } else { - var row = this.Core.CreateRow(childSourceLineNumbers, TupleDefinitionType.WixAction, new Identifier(AccessModifier.Public, sequenceTable, actionName)); - row.Set(0, sequenceTable); - row.Set(1, actionName); - row.Set(2, condition); + var tuple = new WixActionTuple(childSourceLineNumbers, new Identifier(AccessModifier.Public, sequenceTable, actionName)) + { + SequenceTable = sequenceTable, + Action = actionName, + Condition = condition, + Before = beforeAction, + After = afterAction, + Overridable = overridable, + }; + if (CompilerConstants.IntegerNotSet != sequence) { - row.Set(3, sequence); + tuple.Sequence = sequence; } - row.Set(4, beforeAction); - row.Set(5, afterAction); - row.Set(6, overridable ? 1 : 0); + + this.Core.AddTuple(tuple); } } } @@ -3305,7 +3015,7 @@ namespace WixToolset.Core { if (!String.IsNullOrEmpty(delayedAutoStart)) { - var tuple = new MsiServiceConfigTuple(sourceLineNumbers, new Identifier(String.Concat(id.Id, ".DS"), id.Access)) + var tuple = new MsiServiceConfigTuple(sourceLineNumbers, new Identifier(id.Access, String.Concat(id.Id, ".DS"))) { Name = name, OnInstall = install, @@ -3327,7 +3037,7 @@ namespace WixToolset.Core if (!String.IsNullOrEmpty(failureActionsWhen)) { - var tuple = new MsiServiceConfigTuple(sourceLineNumbers, new Identifier(String.Concat(id.Id, ".FA"), id.Access)) + var tuple = new MsiServiceConfigTuple(sourceLineNumbers, new Identifier(id.Access, String.Concat(id.Id, ".FA"))) { Name = name, OnInstall = install, @@ -3349,7 +3059,7 @@ namespace WixToolset.Core if (!String.IsNullOrEmpty(sid)) { - var tuple = new MsiServiceConfigTuple(sourceLineNumbers, new Identifier(String.Concat(id.Id, ".SS"), id.Access)) + var tuple = new MsiServiceConfigTuple(sourceLineNumbers, new Identifier(id.Access, String.Concat(id.Id, ".SS"))) { Name = name, OnInstall = install, @@ -3371,7 +3081,7 @@ namespace WixToolset.Core if (!String.IsNullOrEmpty(requiredPrivileges)) { - var tuple = new MsiServiceConfigTuple(sourceLineNumbers, new Identifier(String.Concat(id.Id, ".RP"), id.Access)) + var tuple = new MsiServiceConfigTuple(sourceLineNumbers, new Identifier(id.Access, String.Concat(id.Id, ".RP"))) { Name = name, OnInstall = install, @@ -3393,7 +3103,7 @@ namespace WixToolset.Core if (!String.IsNullOrEmpty(preShutdownDelay)) { - var tuple = new MsiServiceConfigTuple(sourceLineNumbers, new Identifier(String.Concat(id.Id, ".PD"), id.Access)) + var tuple = new MsiServiceConfigTuple(sourceLineNumbers, new Identifier(id.Access, String.Concat(id.Id, ".PD"))) { Name = name, OnInstall = install, @@ -4320,9 +4030,11 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.FileSFPCatalog); - row.Set(0, id); - row.Set(1, parentSFPCatalog); + this.Core.AddTuple(new FileSFPCatalogTuple(sourceLineNumbers) + { + File_ = id, + SFPCatalog_ = parentSFPCatalog + }); } } @@ -4411,10 +4123,12 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.SFPCatalog); - row.Set(0, name); - row.Set(1, sourceFile); - row.Set(2, dependency); + this.Core.AddTuple(new SFPCatalogTuple(sourceLineNumbers) + { + SFPCatalog = name, + Catalog = sourceFile, + Dependency = dependency + }); } } @@ -4827,10 +4541,12 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiShortcutProperty, id); - row.Set(1, shortcutId); - row.Set(2, key); - row.Set(3, value); + this.Core.AddTuple(new MsiShortcutPropertyTuple(sourceLineNumbers, id) + { + Shortcut_ = shortcutId, + PropertyKey = key, + PropVariantValue = value + }); } } @@ -5022,21 +4738,27 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.TypeLib); - row.Set(0, id); - row.Set(1, language); - row.Set(2, componentId); + var tuple = new TypeLibTuple(sourceLineNumbers) + { + LibId = id, + Language = language, + Component_ = componentId, + Description = description, + Directory_ = helpDirectory, + Feature_ = Guid.Empty.ToString("B") + }; + if (CompilerConstants.IntegerNotSet != majorVersion || CompilerConstants.IntegerNotSet != minorVersion) { - row.Set(3, (CompilerConstants.IntegerNotSet != majorVersion ? majorVersion * 256 : 0) + (CompilerConstants.IntegerNotSet != minorVersion ? minorVersion : 0)); + tuple.Version = (CompilerConstants.IntegerNotSet != majorVersion ? majorVersion * 256 : 0) + (CompilerConstants.IntegerNotSet != minorVersion ? minorVersion : 0); } - row.Set(4, description); - row.Set(5, helpDirectory); - row.Set(6, Guid.Empty.ToString("B")); + if (CompilerConstants.IntegerNotSet != cost) { - row.Set(7, cost); + tuple.Cost = cost; } + + this.Core.AddTuple(tuple); } } else if (YesNoType.No == advertise) @@ -5250,7 +4972,7 @@ namespace WixToolset.Core this.Core.AddTuple(tuple); // Ensure the action property is secure. - this.AddWixPropertyRow(sourceLineNumbers, new Identifier(actionProperty, AccessModifier.Private), false, true, false); + this.AddWixPropertyRow(sourceLineNumbers, new Identifier(AccessModifier.Private, actionProperty), false, true, false); // Ensure that RemoveExistingProducts is authored in InstallExecuteSequence // if at least one row in Upgrade table lacks the OnlyDetect attribute. @@ -5361,15 +5083,20 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Verb); - row.Set(0, extension); - row.Set(1, id); + var tuple = new VerbTuple(sourceLineNumbers) + { + Extension_ = extension, + Verb = id, + Command = command, + Argument = argument, + }; + if (CompilerConstants.IntegerNotSet != sequence) { - row.Set(2, sequence); + tuple.Sequence = sequence; } - row.Set(3, command); - row.Set(4, argument); + + this.Core.AddTuple(tuple); } } else if (YesNoType.No == advertise) @@ -5413,76 +5140,6 @@ namespace WixToolset.Core } } - /// - /// Parses a Wix element. - /// - /// Element to parse. - private void ParseWixElement(XElement node) - { - var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - string requiredVersion = null; - - foreach (var attrib in node.Attributes()) - { - if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) - { - switch (attrib.Name.LocalName) - { - case "RequiredVersion": - requiredVersion = this.Core.GetAttributeVersionValue(sourceLineNumbers, attrib); - break; - default: - this.Core.UnexpectedAttribute(node, attrib); - break; - } - } - else - { - this.Core.ParseExtensionAttribute(node, attrib); - } - } - - if (null != requiredVersion) - { - this.Core.VerifyRequiredVersion(sourceLineNumbers, requiredVersion); - } - - foreach (var child in node.Elements()) - { - if (CompilerCore.WixNamespace == child.Name.Namespace) - { - switch (child.Name.LocalName) - { - case "Bundle": - this.ParseBundleElement(child); - break; - case "Fragment": - this.ParseFragmentElement(child); - break; - case "Module": - this.ParseModuleElement(child); - break; - case "PatchCreation": - this.ParsePatchCreationElement(child); - break; - case "Product": - this.ParseProductElement(child); - break; - case "Patch": - this.ParsePatchElement(child); - break; - default: - this.Core.UnexpectedElement(node, child); - break; - } - } - else - { - this.Core.ParseExtensionElement(node, child); - } - } - } - /// /// Parses a WixVariable element. /// @@ -5534,9 +5191,11 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var wixVariableRow = (WixVariableTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixVariable, id); - wixVariableRow.Value = value; - wixVariableRow.Overridable = overridable; + this.Core.AddTuple(new WixVariableTuple(sourceLineNumbers, id) + { + Value = value, + Overridable = overridable + }); } } diff --git a/src/WixToolset.Core/Compiler_Bundle.cs b/src/WixToolset.Core/Compiler_Bundle.cs index 21028b6f..2ec66333 100644 --- a/src/WixToolset.Core/Compiler_Bundle.cs +++ b/src/WixToolset.Core/Compiler_Bundle.cs @@ -17,9 +17,10 @@ namespace WixToolset.Core /// internal partial class Compiler : ICompiler { - public const string BurnUXContainerId = "WixUXContainer"; - public const string BurnDefaultAttachedContainerId = "WixAttachedContainer"; - + public static readonly Identifier BurnUXContainerId = new Identifier(AccessModifier.Private, "WixUXContainer"); + public static readonly Identifier BurnDefaultAttachedContainerId = new Identifier(AccessModifier.Private, "WixAttachedContainer"); + public static readonly Identifier BundleLayoutOnlyPayloads = new Identifier(AccessModifier.Private, "BundleLayoutOnlyPayloads"); + // The following constants must stay in sync with src\burn\engine\core.h private const string BURN_BUNDLE_NAME = "WixBundleName"; private const string BURN_BUNDLE_ORIGINAL_SOURCE = "WixBundleOriginalSource"; @@ -88,10 +89,14 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var wixApprovedExeForElevationRow = (WixApprovedExeForElevationTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixApprovedExeForElevation, id); - wixApprovedExeForElevationRow.Key = key; - wixApprovedExeForElevationRow.Value = valueName; - wixApprovedExeForElevationRow.Attributes = (int)attributes; + var tuple = new WixApprovedExeForElevationTuple(sourceLineNumbers, id) + { + Key = key, + Value = valueName, + Attributes = attributes + }; + + this.Core.AddTuple(tuple); } } @@ -311,10 +316,10 @@ namespace WixToolset.Core logSeen = true; break; case "PayloadGroup": - this.ParsePayloadGroupElement(child, ComplexReferenceParentType.Layout, "BundleLayoutOnlyPayloads"); + this.ParsePayloadGroupElement(child, ComplexReferenceParentType.Layout, Compiler.BundleLayoutOnlyPayloads); break; case "PayloadGroupRef": - this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Layout, "BundleLayoutOnlyPayloads", ComplexReferenceChildType.Unknown, null); + this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Layout, Compiler.BundleLayoutOnlyPayloads, ComplexReferenceChildType.Unknown, null); break; case "RelatedBundle": this.ParseRelatedBundleElement(child); @@ -348,72 +353,75 @@ namespace WixToolset.Core { if (null != upgradeCode) { - var tuple = new WixRelatedBundleTuple(sourceLineNumbers) + this.Core.AddTuple(new WixRelatedBundleTuple(sourceLineNumbers) { BundleId = upgradeCode, Action = RelatedBundleActionType.Upgrade, - }; - - this.Core.AddTuple(tuple); + }); } - var containerRow = (WixBundleContainerTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleContainer); - containerRow.WixBundleContainer = Compiler.BurnDefaultAttachedContainerId; - containerRow.Name = "bundle-attached.cab"; - containerRow.Type = ContainerType.Attached; + this.Core.AddTuple(new WixBundleContainerTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, Compiler.BurnDefaultAttachedContainerId)) + { + Name = "bundle-attached.cab", + Type = ContainerType.Attached + }); - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundle); - row.Set(0, version); - row.Set(1, copyright); - row.Set(2, name); - row.Set(3, aboutUrl); + var bundleTuple = this.Core.CreateTuple(sourceLineNumbers, TupleDefinitionType.WixBundle); + bundleTuple.Set(0, version); + bundleTuple.Set(1, copyright); + bundleTuple.Set(2, name); + bundleTuple.Set(3, aboutUrl); if (-1 != disableModify) { - row.Set(4, disableModify); + bundleTuple.Set(4, disableModify); } if (YesNoType.NotSet != disableRemove) { - row.Set(5, (YesNoType.Yes == disableRemove) ? 1 : 0); + bundleTuple.Set(5, (YesNoType.Yes == disableRemove) ? 1 : 0); } // row.Set(6] - (deprecated) "disable repair" - row.Set(7, helpTelephone); - row.Set(8, helpUrl); - row.Set(9, manufacturer); - row.Set(10, updateUrl); + bundleTuple.Set(7, helpTelephone); + bundleTuple.Set(8, helpUrl); + bundleTuple.Set(9, manufacturer); + bundleTuple.Set(10, updateUrl); if (YesNoDefaultType.Default != compressed) { - row.Set(11, (YesNoDefaultType.Yes == compressed) ? 1 : 0); + bundleTuple.Set(11, (YesNoDefaultType.Yes == compressed) ? 1 : 0); } - row.Set(12, logVariablePrefixAndExtension); - row.Set(13, iconSourceFile); - row.Set(14, splashScreenSourceFile); - row.Set(15, condition); - row.Set(16, tag); - row.Set(17, this.CurrentPlatform.ToString()); - row.Set(18, parentName); - row.Set(19, upgradeCode); + bundleTuple.Set(12, logVariablePrefixAndExtension); + bundleTuple.Set(13, iconSourceFile); + bundleTuple.Set(14, splashScreenSourceFile); + bundleTuple.Set(15, condition); + bundleTuple.Set(16, tag); + bundleTuple.Set(17, this.CurrentPlatform.ToString()); + bundleTuple.Set(18, parentName); + bundleTuple.Set(19, upgradeCode); // Ensure that the bundle stores the well-known persisted values. - var bundleNameWellKnownVariable = (WixBundleVariableTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleVariable); - bundleNameWellKnownVariable.WixBundleVariable = Compiler.BURN_BUNDLE_NAME; - bundleNameWellKnownVariable.Hidden = false; - bundleNameWellKnownVariable.Persisted = true; - - var bundleOriginalSourceWellKnownVariable = (WixBundleVariableTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleVariable); - bundleOriginalSourceWellKnownVariable.WixBundleVariable = Compiler.BURN_BUNDLE_ORIGINAL_SOURCE; - bundleOriginalSourceWellKnownVariable.Hidden = false; - bundleOriginalSourceWellKnownVariable.Persisted = true; - - var bundleOriginalSourceFolderWellKnownVariable = (WixBundleVariableTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleVariable); - bundleOriginalSourceFolderWellKnownVariable.WixBundleVariable = Compiler.BURN_BUNDLE_ORIGINAL_SOURCE_FOLDER; - bundleOriginalSourceFolderWellKnownVariable.Hidden = false; - bundleOriginalSourceFolderWellKnownVariable.Persisted = true; - - var bundleLastUsedSourceWellKnownVariable = (WixBundleVariableTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleVariable); - bundleLastUsedSourceWellKnownVariable.WixBundleVariable = Compiler.BURN_BUNDLE_LAST_USED_SOURCE; - bundleLastUsedSourceWellKnownVariable.Hidden = false; - bundleLastUsedSourceWellKnownVariable.Persisted = true; + this.Core.AddTuple(new WixBundleVariableTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, Compiler.BURN_BUNDLE_NAME)) + { + Hidden = false, + Persisted = true + }); + + this.Core.AddTuple(new WixBundleVariableTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, Compiler.BURN_BUNDLE_ORIGINAL_SOURCE)) + { + Hidden = false, + Persisted = true + }); + + this.Core.AddTuple(new WixBundleVariableTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, Compiler.BURN_BUNDLE_ORIGINAL_SOURCE_FOLDER)) + { + Hidden = false, + Persisted = true + }); + + this.Core.AddTuple(new WixBundleVariableTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, Compiler.BURN_BUNDLE_LAST_USED_SOURCE)) + { + Hidden = false, + Persisted = true + }); } } @@ -514,8 +522,10 @@ namespace WixToolset.Core { this.CreatePayloadRow(sourceLineNumbers, id, Path.GetFileName(sourceFile), sourceFile, null, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, ComplexReferenceChildType.Unknown, null, YesNoDefaultType.Yes, YesNoType.Yes, null, null, null); - var wixCatalogRow = (WixBundleCatalogTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleCatalog, id); - wixCatalogRow.Payload_ = id.Id; + this.Core.AddTuple(new WixBundleCatalogTuple(sourceLineNumbers, id) + { + Payload_ = id.Id, + }); } } @@ -614,10 +624,12 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = (WixBundleContainerTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleContainer, id); - row.Name = name; - row.Type = type; - row.DownloadUrl = downloadUrl; + this.Core.AddTuple(new WixBundleContainerTuple(sourceLineNumbers, id) + { + Name = name, + Type = type, + DownloadUrl = downloadUrl + }); } } @@ -628,12 +640,11 @@ namespace WixToolset.Core private void ParseBootstrapperApplicationElement(XElement node) { var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - string id = null; - string previousId = null; + Identifier previousId = null; var previousType = ComplexReferenceChildType.Unknown; // The BootstrapperApplication element acts like a Payload element so delegate to the "Payload" attribute parsing code to parse and create a Payload entry. - id = this.ParsePayloadElementContent(node, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, previousType, previousId, false); + var id = this.ParsePayloadElementContent(node, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, previousType, previousId, false); if (null != id) { previousId = id; @@ -676,15 +687,15 @@ namespace WixToolset.Core // Add the application as an attached container and if an Id was provided add that too. if (!this.Core.EncounteredError) { - var containerRow = (WixBundleContainerTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleContainer); - containerRow.WixBundleContainer = Compiler.BurnUXContainerId; - containerRow.Name = "bundle-ux.cab"; - containerRow.Type = ContainerType.Attached; + this.Core.AddTuple(new WixBundleContainerTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, Compiler.BurnUXContainerId)) + { + Name = "bundle-ux.cab", + Type = ContainerType.Attached + }); - if (!String.IsNullOrEmpty(id)) + if (null != id) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBootstrapperApplication); - row.Set(0, id); + this.Core.AddTuple(new WixBootstrapperApplicationTuple(sourceLineNumbers, id)); } } } @@ -697,7 +708,7 @@ namespace WixToolset.Core { var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); string id = null; - string previousId = null; + Identifier previousId = null; var previousType = ComplexReferenceChildType.Unknown; foreach (var attrib in node.Attributes()) @@ -847,12 +858,14 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixUpdateRegistration); - row.Set(0, manufacturer); - row.Set(1, department); - row.Set(2, productFamily); - row.Set(3, name); - row.Set(4, classification); + this.Core.AddTuple(new WixUpdateRegistrationTuple(sourceLineNumbers) + { + Manufacturer = manufacturer, + Department = department, + ProductFamily = productFamily, + Name = name, + Classification = classification + }); } } @@ -862,7 +875,7 @@ namespace WixToolset.Core /// Element to parse /// ComplexReferenceParentType of parent element. (BA or PayloadGroup) /// Identifier of parent element. - private string ParsePayloadElement(XElement node, ComplexReferenceParentType parentType, string parentId, ComplexReferenceChildType previousType, string previousId) + private Identifier ParsePayloadElement(XElement node, ComplexReferenceParentType parentType, Identifier parentId, ComplexReferenceChildType previousType, Identifier previousId) { Debug.Assert(ComplexReferenceParentType.PayloadGroup == parentType || ComplexReferenceParentType.Package == parentType || ComplexReferenceParentType.Container == parentType); Debug.Assert(ComplexReferenceChildType.Unknown == previousType || ComplexReferenceChildType.PayloadGroup == previousType || ComplexReferenceChildType.Payload == previousType); @@ -870,7 +883,7 @@ namespace WixToolset.Core var id = this.ParsePayloadElementContent(node, parentType, parentId, previousType, previousId, true); var context = new Dictionary { - ["Id"] = id + ["Id"] = id.Id }; foreach (var child in node.Elements()) @@ -899,7 +912,7 @@ namespace WixToolset.Core /// Element to parse /// ComplexReferenceParentType of parent element. /// Identifier of parent element. - private string ParsePayloadElementContent(XElement node, ComplexReferenceParentType parentType, string parentId, ComplexReferenceChildType previousType, string previousId, bool required) + private Identifier ParsePayloadElementContent(XElement node, ComplexReferenceParentType parentType, Identifier parentId, ComplexReferenceChildType previousType, Identifier previousId, bool required) { Debug.Assert(ComplexReferenceParentType.PayloadGroup == parentType || ComplexReferenceParentType.Package == parentType || ComplexReferenceParentType.Container == parentType); @@ -959,7 +972,7 @@ namespace WixToolset.Core if (null == id) { - id = this.Core.CreateIdentifier("pay", (null != sourceFile) ? sourceFile.ToUpperInvariant() : String.Empty); + id = this.Core.CreateIdentifier("pay", sourceFile?.ToUpperInvariant() ?? String.Empty); } // Now that the PayloadId is known, we can parse the extension attributes. @@ -1022,7 +1035,7 @@ namespace WixToolset.Core this.CreatePayloadRow(sourceLineNumbers, id, name, sourceFile, downloadUrl, parentType, parentId, previousType, previousId, compressed, enableSignatureVerification, null, null, remotePayload); - return id.Id; + return id; } private RemotePayload ParseRemotePayloadElement(XElement node) @@ -1103,38 +1116,42 @@ namespace WixToolset.Core /// ComplexReferenceParentType of parent element /// Identifier of parent element. private WixBundlePayloadTuple CreatePayloadRow(SourceLineNumber sourceLineNumbers, Identifier id, string name, string sourceFile, string downloadUrl, ComplexReferenceParentType parentType, - string parentId, ComplexReferenceChildType previousType, string previousId, YesNoDefaultType compressed, YesNoType enableSignatureVerification, string displayName, string description, + Identifier parentId, ComplexReferenceChildType previousType, Identifier previousId, YesNoDefaultType compressed, YesNoType enableSignatureVerification, string displayName, string description, RemotePayload remotePayload) { - WixBundlePayloadTuple row = null; + WixBundlePayloadTuple tuple = null; if (!this.Core.EncounteredError) { - row = (WixBundlePayloadTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundlePayload, id); - row.Name = String.IsNullOrEmpty(name) ? Path.GetFileName(sourceFile) : name; - row.SourceFile = sourceFile; - row.DownloadUrl = downloadUrl; - row.Compressed = compressed; - row.UnresolvedSourceFile = sourceFile; // duplicate of sourceFile but in a string column so it won't get resolved to a full path during binding. - row.DisplayName = displayName; - row.Description = description; - row.EnableSignatureValidation = (YesNoType.Yes == enableSignatureVerification); + tuple = new WixBundlePayloadTuple(sourceLineNumbers, id) + { + Name = String.IsNullOrEmpty(name) ? Path.GetFileName(sourceFile) : name, + SourceFile = sourceFile, + DownloadUrl = downloadUrl, + Compressed = compressed, + UnresolvedSourceFile = sourceFile, // duplicate of sourceFile but in a string column so it won't get resolved to a full path during binding. + DisplayName = displayName, + Description = description, + EnableSignatureValidation = (YesNoType.Yes == enableSignatureVerification) + }; if (null != remotePayload) { - row.Description = remotePayload.Description; - row.DisplayName = remotePayload.ProductName; - row.Hash = remotePayload.Hash; - row.PublicKey = remotePayload.CertificatePublicKey; - row.Thumbprint = remotePayload.CertificateThumbprint; - row.FileSize = remotePayload.Size; - row.Version = remotePayload.Version; + tuple.Description = remotePayload.Description; + tuple.DisplayName = remotePayload.ProductName; + tuple.Hash = remotePayload.Hash; + tuple.PublicKey = remotePayload.CertificatePublicKey; + tuple.Thumbprint = remotePayload.CertificateThumbprint; + tuple.FileSize = remotePayload.Size; + tuple.Version = remotePayload.Version; } - this.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId, ComplexReferenceChildType.Payload, id.Id, previousType, previousId); + this.Core.AddTuple(tuple); + + this.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId.Id, ComplexReferenceChildType.Payload, id.Id, previousType, previousId.Id); } - return row; + return tuple; } /// @@ -1143,7 +1160,7 @@ namespace WixToolset.Core /// Element to parse /// Optional ComplexReferenceParentType of parent element. (typically another PayloadGroup) /// Identifier of parent element. - private void ParsePayloadGroupElement(XElement node, ComplexReferenceParentType parentType, string parentId) + private void ParsePayloadGroupElement(XElement node, ComplexReferenceParentType parentType, Identifier parentId) { Debug.Assert(ComplexReferenceParentType.Unknown == parentType || ComplexReferenceParentType.Layout == parentType || ComplexReferenceParentType.PayloadGroup == parentType); @@ -1177,7 +1194,7 @@ namespace WixToolset.Core } var previousType = ComplexReferenceChildType.Unknown; - string previousId = null; + Identifier previousId = null; foreach (var child in node.Elements()) { if (CompilerCore.WixNamespace == child.Name.Namespace) @@ -1185,11 +1202,11 @@ namespace WixToolset.Core switch (child.Name.LocalName) { case "Payload": - previousId = this.ParsePayloadElement(child, ComplexReferenceParentType.PayloadGroup, id.Id, previousType, previousId); + previousId = this.ParsePayloadElement(child, ComplexReferenceParentType.PayloadGroup, id, previousType, previousId); previousType = ComplexReferenceChildType.Payload; break; case "PayloadGroupRef": - previousId = this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.PayloadGroup, id.Id, previousType, previousId); + previousId = this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.PayloadGroup, id, previousType, previousId); previousType = ComplexReferenceChildType.PayloadGroup; break; default: @@ -1206,9 +1223,9 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundlePayloadGroup, id); + this.Core.AddTuple(new WixBundlePayloadGroupTuple(sourceLineNumbers, id)); - this.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId, ComplexReferenceChildType.PayloadGroup, id.Id, ComplexReferenceChildType.Unknown, null); + this.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId?.Id, ComplexReferenceChildType.PayloadGroup, id.Id, ComplexReferenceChildType.Unknown, null); } } @@ -1218,13 +1235,13 @@ namespace WixToolset.Core /// Element to parse. /// ComplexReferenceParentType of parent element (BA or PayloadGroup). /// Identifier of parent element. - private string ParsePayloadGroupRefElement(XElement node, ComplexReferenceParentType parentType, string parentId, ComplexReferenceChildType previousType, string previousId) + private Identifier ParsePayloadGroupRefElement(XElement node, ComplexReferenceParentType parentType, Identifier parentId, ComplexReferenceChildType previousType, Identifier previousId) { Debug.Assert(ComplexReferenceParentType.Layout == parentType || ComplexReferenceParentType.PayloadGroup == parentType || ComplexReferenceParentType.Package == parentType || ComplexReferenceParentType.Container == parentType); Debug.Assert(ComplexReferenceChildType.Unknown == previousType || ComplexReferenceChildType.PayloadGroup == previousType || ComplexReferenceChildType.Payload == previousType); var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); - string id = null; + Identifier id = null; foreach (var attrib in node.Attributes()) { @@ -1233,8 +1250,8 @@ namespace WixToolset.Core switch (attrib.Name.LocalName) { case "Id": - id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); - this.Core.CreateSimpleReference(sourceLineNumbers, "WixBundlePayloadGroup", id); + id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib); + this.Core.CreateSimpleReference(sourceLineNumbers, "WixBundlePayloadGroup", id.Id); break; default: this.Core.UnexpectedAttribute(node, attrib); @@ -1254,7 +1271,7 @@ namespace WixToolset.Core this.Core.ParseForExtensionElements(node); - this.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId, ComplexReferenceChildType.PayloadGroup, id, previousType, previousId); + this.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId.Id, ComplexReferenceChildType.PayloadGroup, id.Id, previousType, previousId.Id); return id; } @@ -1274,6 +1291,11 @@ namespace WixToolset.Core ComplexReferenceChildType type, string id, ComplexReferenceChildType previousType, string previousId) { + if (this.Core.EncounteredError) + { + return; + } + if (ComplexReferenceParentType.Unknown != parentType && null != parentId) { this.Core.CreateWixGroupRow(sourceLineNumbers, parentType, parentId, type, id); @@ -1281,7 +1303,18 @@ namespace WixToolset.Core if (ComplexReferenceChildType.Unknown != previousType && null != previousId) { - this.CreateWixOrderingRow(sourceLineNumbers, type, id, previousType, previousId); + // TODO: Should we define our own enum for this, just to ensure there's no "cross-contamination"? + // TODO: Also, we could potentially include an 'Attributes' field to track things like + // 'before' vs. 'after', and explicit vs. inferred dependencies. + var tuple = new WixOrderingTuple(sourceLineNumbers) + { + ItemType = type, + ItemId_ = id, + DependsOnType = previousType, + DependsOnId_ = previousId + }; + + this.Core.AddTuple(tuple); } } @@ -1307,7 +1340,7 @@ namespace WixToolset.Core break; case "Behavior": var behaviorString = this.Core.GetAttributeValue(sourceLineNumbers, attrib); - if (!Enum.TryParse(behaviorString, true, out behavior)) + if (!Enum.TryParse(behaviorString, true, out behavior)) { this.Core.Write(ErrorMessages.IllegalAttributeValueWithLegalList(sourceLineNumbers, node.Name.LocalName, "Behavior", behaviorString, "success, error, scheduleReboot, forceReboot")); } @@ -1332,10 +1365,12 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = (WixBundlePackageExitCodeTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundlePackageExitCode); - row.ChainPackageId = packageId; - row.Code = value; - row.Behavior = behavior; + this.Core.AddTuple(new WixBundlePackageExitCodeTuple(sourceLineNumbers) + { + ChainPackageId = packageId, + Code = value, + Behavior = behavior + }); } } @@ -1384,7 +1419,7 @@ namespace WixToolset.Core } // Ensure there is always a rollback boundary at the beginning of the chain. - this.CreateRollbackBoundary(sourceLineNumbers, new Identifier("WixDefaultBoundary", AccessModifier.Public), YesNoType.Yes, YesNoType.No, ComplexReferenceParentType.PackageGroup, "WixChain", ComplexReferenceChildType.Unknown, null); + this.CreateRollbackBoundary(sourceLineNumbers, new Identifier(AccessModifier.Public, "WixDefaultBoundary"), YesNoType.Yes, YesNoType.No, ComplexReferenceParentType.PackageGroup, "WixChain", ComplexReferenceChildType.Unknown, null); var previousId = "WixDefaultBoundary"; var previousType = ComplexReferenceChildType.Package; @@ -1438,8 +1473,10 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = (WixChainTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixChain); - row.Attributes = attributes; + this.Core.AddTuple(new WixChainTuple(sourceLineNumbers) + { + Attributes = attributes + }); } } @@ -1680,7 +1717,24 @@ namespace WixToolset.Core installCondition = this.Core.GetAttributeValue(sourceLineNumbers, attrib); break; case "Cache": - cache = this.Core.GetAttributeYesNoAlwaysValue(sourceLineNumbers, attrib); + var value = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + switch (value) + { + case "always": + cache = YesNoAlwaysType.Always; + break; + case "yes": + cache = YesNoAlwaysType.Yes; + break; + case "no": + cache = YesNoAlwaysType.No; + break; + case "": + break; + default: + this.Core.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, value, "button", "yes", "no")); + break; + } break; case "CacheId": cacheId = this.Core.GetAttributeValue(sourceLineNumbers, attrib); @@ -1933,10 +1987,10 @@ namespace WixToolset.Core } break; case "Payload": - this.ParsePayloadElement(child, ComplexReferenceParentType.Package, id.Id, ComplexReferenceChildType.Unknown, null); + this.ParsePayloadElement(child, ComplexReferenceParentType.Package, id, ComplexReferenceChildType.Unknown, null); break; case "PayloadGroupRef": - this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Package, id.Id, ComplexReferenceChildType.Unknown, null); + this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Package, id, ComplexReferenceChildType.Unknown, null); break; case "ExitCode": allowed = (packageType == WixBundlePackageType.Exe); @@ -1975,60 +2029,60 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { // We create the package contents as a payload with this package as the parent - this.CreatePayloadRow(sourceLineNumbers, id, name, sourceFile, downloadUrl, ComplexReferenceParentType.Package, id.Id, + this.CreatePayloadRow(sourceLineNumbers, id, name, sourceFile, downloadUrl, ComplexReferenceParentType.Package, id, ComplexReferenceChildType.Unknown, null, compressed, enableSignatureVerification, displayName, description, remotePayload); - var chainItemRow = (WixChainItemTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixChainItem, id); + this.Core.AddTuple(new WixChainItemTuple(sourceLineNumbers, id)); WixBundlePackageAttributes attributes = 0; attributes |= (YesNoType.Yes == permanent) ? WixBundlePackageAttributes.Permanent : 0; attributes |= (YesNoType.Yes == visible) ? WixBundlePackageAttributes.Visible : 0; - var chainPackageRow = (WixBundlePackageTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundlePackage, id); - chainPackageRow.Type = packageType; - chainPackageRow.Payload_ = id.Id; - chainPackageRow.Attributes = attributes; - - chainPackageRow.InstallCondition = installCondition; + var chainPackageTuple = new WixBundlePackageTuple(sourceLineNumbers, id) + { + Type = packageType, + Payload_ = id.Id, + Attributes = attributes, + InstallCondition = installCondition, + CacheId = cacheId, + LogPathVariable = logPathVariable, + RollbackLogPathVariable = rollbackPathVariable, + }; if (YesNoAlwaysType.NotSet != cache) { - chainPackageRow.Cache = cache; + chainPackageTuple.Cache = cache; } - chainPackageRow.CacheId = cacheId; - if (YesNoType.NotSet != vital) { - chainPackageRow.Vital = (vital == YesNoType.Yes); + chainPackageTuple.Vital = (vital == YesNoType.Yes); } if (YesNoDefaultType.NotSet != perMachine) { - chainPackageRow.PerMachine = perMachine; + chainPackageTuple.PerMachine = perMachine; } - chainPackageRow.LogPathVariable = logPathVariable; - chainPackageRow.RollbackLogPathVariable = rollbackPathVariable; - if (CompilerConstants.IntegerNotSet != installSize) { - chainPackageRow.InstallSize = installSize; + chainPackageTuple.InstallSize = installSize; } + this.Core.AddTuple(chainPackageTuple); + switch (packageType) { case WixBundlePackageType.Exe: - WixBundleExePackageAttributes exeAttributes = 0; - exeAttributes |= (YesNoType.Yes == repairable) ? WixBundleExePackageAttributes.Repairable : 0; - - var exeRow = (WixBundleExePackageTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleExePackage, id); - exeRow.Attributes = exeAttributes; - exeRow.DetectCondition = detectCondition; - exeRow.InstallCommand = installCommand; - exeRow.RepairCommand = repairCommand; - exeRow.UninstallCommand = uninstallCommand; - exeRow.ExeProtocol = protocol; + this.Core.AddTuple(new WixBundleExePackageTuple(sourceLineNumbers, id) + { + Attributes = (YesNoType.Yes == repairable) ? WixBundleExePackageAttributes.Repairable : 0, + DetectCondition = detectCondition, + InstallCommand = installCommand, + RepairCommand = repairCommand, + UninstallCommand = uninstallCommand, + ExeProtocol = protocol + }); break; case WixBundlePackageType.Msi: @@ -2038,8 +2092,10 @@ namespace WixToolset.Core msiAttributes |= (YesNoType.Yes == forcePerMachine) ? WixBundleMsiPackageAttributes.ForcePerMachine : 0; msiAttributes |= (YesNoType.Yes == suppressLooseFilePayloadGeneration) ? WixBundleMsiPackageAttributes.SuppressLooseFilePayloadGeneration : 0; - var msiRow = (WixBundleMsiPackageTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleMsiPackage, id); - msiRow.Attributes = msiAttributes; + this.Core.AddTuple(new WixBundleMsiPackageTuple(sourceLineNumbers, id) + { + Attributes = msiAttributes + }); break; case WixBundlePackageType.Msp: @@ -2047,14 +2103,18 @@ namespace WixToolset.Core mspAttributes |= (YesNoType.Yes == displayInternalUI) ? WixBundleMspPackageAttributes.DisplayInternalUI : 0; mspAttributes |= (YesNoType.Yes == slipstream) ? WixBundleMspPackageAttributes.Slipstream : 0; - var mspRow = (WixBundleMspPackageTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleMspPackage, id); - mspRow.Attributes = mspAttributes; + this.Core.AddTuple(new WixBundleMspPackageTuple(sourceLineNumbers, id) + { + Attributes = mspAttributes + }); break; case WixBundlePackageType.Msu: - var msuRow = (WixBundleMsuPackageTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleMsuPackage, id); - msuRow.DetectCondition = detectCondition; - msuRow.MsuKB = msuKB; + this.Core.AddTuple(new WixBundleMsuPackageTuple(sourceLineNumbers, id) + { + DetectCondition = detectCondition, + MsuKB = msuKB + }); break; } @@ -2114,12 +2174,14 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = (WixBundlePackageCommandLineTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundlePackageCommandLine); - row.WixBundlePackage_ = packageId; - row.InstallArgument = installArgument; - row.UninstallArgument = uninstallArgument; - row.RepairArgument = repairArgument; - row.Condition = condition; + this.Core.AddTuple(new WixBundlePackageCommandLineTuple(sourceLineNumbers) + { + WixBundlePackage_ = packageId, + InstallArgument = installArgument, + UninstallArgument = uninstallArgument, + RepairArgument = repairArgument, + Condition = condition + }); } } @@ -2204,7 +2266,7 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundlePackageGroup, id); + this.Core.AddTuple(new WixBundlePackageGroupTuple(sourceLineNumbers, id)); } } @@ -2299,19 +2361,22 @@ namespace WixToolset.Core /// Identifier of previous item, if any. private void CreateRollbackBoundary(SourceLineNumber sourceLineNumbers, Identifier id, YesNoType vital, YesNoType transaction, ComplexReferenceParentType parentType, string parentId, ComplexReferenceChildType previousType, string previousId) { - var row = (WixChainItemTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixChainItem, id); + this.Core.AddTuple(new WixChainItemTuple(sourceLineNumbers, id)); - var rollbackBoundary = (WixBundleRollbackBoundaryTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleRollbackBoundary, id); + var rollbackBoundary = new WixBundleRollbackBoundaryTuple(sourceLineNumbers, id); if (YesNoType.NotSet != vital) { rollbackBoundary.Vital = (vital == YesNoType.Yes); } + if (YesNoType.NotSet != transaction) { rollbackBoundary.Transaction = (transaction == YesNoType.Yes); } + this.Core.AddTuple(rollbackBoundary); + this.CreateChainPackageMetaRows(sourceLineNumbers, parentType, parentId, ComplexReferenceChildType.Package, id.Id, previousType, previousId, null); } @@ -2341,23 +2406,6 @@ namespace WixToolset.Core this.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId, type, id, previousType, previousId); } - // TODO: Should we define our own enum for this, just to ensure there's no "cross-contamination"? - // TODO: Also, we could potentially include an 'Attributes' field to track things like - // 'before' vs. 'after', and explicit vs. inferred dependencies. - private void CreateWixOrderingRow(SourceLineNumber sourceLineNumbers, - ComplexReferenceChildType itemType, string itemId, - ComplexReferenceChildType dependsOnType, string dependsOnId) - { - if (!this.Core.EncounteredError) - { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixOrdering); - row.Set(0, itemType.ToString()); - row.Set(1, itemId); - row.Set(2, dependsOnType.ToString()); - row.Set(3, dependsOnId); - } - } - /// /// Parse MsiProperty element /// @@ -2410,15 +2458,19 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = (WixBundleMsiPropertyTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleMsiProperty); - row.WixBundlePackage_ = packageId; - row.Name = name; - row.Value = value; + var tuple = new WixBundleMsiPropertyTuple(sourceLineNumbers) + { + WixBundlePackage_ = packageId, + Name = name, + Value = value + }; if (!String.IsNullOrEmpty(condition)) { - row.Condition = condition; + tuple.Condition = condition; } + + this.Core.AddTuple(tuple); } } @@ -2462,9 +2514,11 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = (WixBundleSlipstreamMspTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleSlipstreamMsp); - row.WixBundlePackage_ = packageId; - row.WixBundlePackage_Msp = id; + this.Core.AddTuple(new WixBundleSlipstreamMspTuple(sourceLineNumbers) + { + WixBundlePackage_ = packageId, + WixBundlePackage_Msp = id + }); } } @@ -2585,8 +2639,12 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleUpdate); - row.Set(0, location); + var tuple = new WixBundleUpdateTuple(sourceLineNumbers) + { + Location = location + }; + + this.Core.AddTuple(tuple); } } @@ -2698,12 +2756,15 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = (WixBundleVariableTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleVariable); - row.WixBundleVariable = name; - row.Value = value; - row.Type = type; - row.Hidden = hidden; - row.Persisted = persisted; + var tuple = new WixBundleVariableTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, name)) + { + Value = value, + Type = type, + Hidden = hidden, + Persisted = persisted + }; + + this.Core.AddTuple(tuple); } } diff --git a/src/WixToolset.Core/Compiler_EmbeddedUI.cs b/src/WixToolset.Core/Compiler_EmbeddedUI.cs index 3245941e..e71c2f56 100644 --- a/src/WixToolset.Core/Compiler_EmbeddedUI.cs +++ b/src/WixToolset.Core/Compiler_EmbeddedUI.cs @@ -91,11 +91,13 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiEmbeddedChainer, id); - row.Set(1, condition); - row.Set(2, commandLine); - row.Set(3, source); - row.Set(4, type); + this.Core.AddTuple(new MsiEmbeddedChainerTuple(sourceLineNumbers, id) + { + Condition = condition, + CommandLine = commandLine, + Source = source, + Type = type + }); } } diff --git a/src/WixToolset.Core/Compiler_Module.cs b/src/WixToolset.Core/Compiler_Module.cs index b95b5f03..e1563808 100644 --- a/src/WixToolset.Core/Compiler_Module.cs +++ b/src/WixToolset.Core/Compiler_Module.cs @@ -100,11 +100,19 @@ namespace WixToolset.Core switch (child.Name.LocalName) { case "AdminExecuteSequence": + this.ParseSequenceElement(child, SequenceTable.AdminExecuteSequence); + break; case "AdminUISequence": + this.ParseSequenceElement(child, SequenceTable.AdminUISequence); + break; case "AdvertiseExecuteSequence": + this.ParseSequenceElement(child, SequenceTable.AdvertiseExecuteSequence); + break; case "InstallExecuteSequence": + this.ParseSequenceElement(child, SequenceTable.InstallExecuteSequence); + break; case "InstallUISequence": - this.ParseSequenceElement(child, child.Name.LocalName); + this.ParseSequenceElement(child, SequenceTable.InstallUISequence); break; case "AppId": this.ParseAppIdElement(child, null, YesNoType.Yes, null, null, null); @@ -208,10 +216,15 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ModuleSignature); - row.Set(0, this.activeName); - row.Set(1, this.activeLanguage); - row.Set(2, version); + var tuple = new ModuleSignatureTuple(sourceLineNumbers, new Identifier(AccessModifier.Public, this.activeName, this.activeLanguage)) + { + ModuleID = this.activeName, + Version = version + }; + + tuple.Set((int)ModuleSignatureTupleFields.Language, this.activeLanguage); + + this.Core.AddTuple(tuple); } } finally @@ -273,12 +286,17 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ModuleDependency); - row.Set(0, this.activeName); - row.Set(1, this.activeLanguage); - row.Set(2, requiredId); - row.Set(3, requiredLanguage.ToString(CultureInfo.InvariantCulture)); - row.Set(4, requiredVersion); + var tuple = new ModuleDependencyTuple(sourceLineNumbers) + { + ModuleID = this.activeName, + RequiredID = requiredId, + RequiredLanguage = requiredLanguage, + RequiredVersion = requiredVersion + }; + + tuple.Set((int)ModuleDependencyTupleFields.ModuleLanguage, this.activeLanguage); + + this.Core.AddTuple(tuple); } } @@ -351,13 +369,18 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ModuleExclusion); - row.Set(0, this.activeName); - row.Set(1, this.activeLanguage); - row.Set(2, excludedId); - row.Set(3, excludedLanguageField); - row.Set(4, excludedMinVersion); - row.Set(5, excludedMaxVersion); + var tuple = new ModuleExclusionTuple(sourceLineNumbers) + { + ModuleID = this.activeName, + ExcludedID = excludedId, + ExcludedMinVersion = excludedMinVersion, + ExcludedMaxVersion = excludedMaxVersion + }; + + tuple.Set((int)ModuleExclusionTupleFields.ModuleLanguage, this.activeLanguage); + tuple.Set((int)ModuleExclusionTupleFields.ExcludedLanguage, excludedLanguageField); + + this.Core.AddTuple(tuple); } } @@ -548,11 +571,15 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ModuleSubstitution); - row.Set(0, table); - row.Set(1, rowKeys); - row.Set(2, column); - row.Set(3, value); + var tuple = new ModuleSubstitutionTuple(sourceLineNumbers) + { + Table = table, + Row = rowKeys, + Column = column, + Value = value + }; + + this.Core.AddTuple(tuple); } } @@ -599,8 +626,7 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixSuppressModularization); - row.Set(0, name); + this.Core.AddTuple(new WixSuppressModularizationTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, name))); } } @@ -642,8 +668,7 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ModuleIgnoreTable); - row.Set(0, id); + this.Core.AddTuple(new ModuleIgnoreTableTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, id))); } } } diff --git a/src/WixToolset.Core/Compiler_Patch.cs b/src/WixToolset.Core/Compiler_Patch.cs new file mode 100644 index 00000000..42951543 --- /dev/null +++ b/src/WixToolset.Core/Compiler_Patch.cs @@ -0,0 +1,655 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Core +{ + using System; + using System.Collections.Generic; + using System.Diagnostics; + using System.Globalization; + using System.Xml.Linq; + using WixToolset.Data; + using WixToolset.Data.Tuples; + using WixToolset.Extensibility; + + /// + /// Compiler of the WiX toolset. + /// + internal partial class Compiler : ICompiler + { + /// + /// Parses an patch element. + /// + /// The element to parse. + private void ParsePatchElement(XElement node) + { + var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + string patchId = null; + var codepage = 0; + ////bool versionMismatches = false; + ////bool productMismatches = false; + var allowRemoval = false; + string classification = null; + string clientPatchId = null; + string description = null; + string displayName = null; + string comments = null; + string manufacturer = null; + var minorUpdateTargetRTM = YesNoType.NotSet; + string moreInfoUrl = null; + var optimizeCA = CompilerConstants.IntegerNotSet; + var optimizedInstallMode = YesNoType.NotSet; + string targetProductName = null; + // string replaceGuids = String.Empty; + var apiPatchingSymbolFlags = 0; + var optimizePatchSizeForLargeFiles = false; + + foreach (var attrib in node.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + patchId = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, true); + break; + case "Codepage": + codepage = this.Core.GetAttributeCodePageValue(sourceLineNumbers, attrib); + break; + case "AllowMajorVersionMismatches": + ////versionMismatches = (YesNoType.Yes == this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib)); + break; + case "AllowProductCodeMismatches": + ////productMismatches = (YesNoType.Yes == this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib)); + break; + case "AllowRemoval": + allowRemoval = (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)); + break; + case "Classification": + classification = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "ClientPatchId": + clientPatchId = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Description": + description = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "DisplayName": + displayName = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Comments": + comments = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Manufacturer": + manufacturer = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "MinorUpdateTargetRTM": + minorUpdateTargetRTM = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; + case "MoreInfoURL": + moreInfoUrl = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "OptimizedInstallMode": + optimizedInstallMode = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; + case "TargetProductName": + targetProductName = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "ApiPatchingSymbolNoImagehlpFlag": + apiPatchingSymbolFlags |= (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) ? (int)PatchSymbolFlagsType.PATCH_SYMBOL_NO_IMAGEHLP : 0; + break; + case "ApiPatchingSymbolNoFailuresFlag": + apiPatchingSymbolFlags |= (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) ? (int)PatchSymbolFlagsType.PATCH_SYMBOL_NO_FAILURES : 0; + break; + case "ApiPatchingSymbolUndecoratedTooFlag": + apiPatchingSymbolFlags |= (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) ? (int)PatchSymbolFlagsType.PATCH_SYMBOL_UNDECORATED_TOO : 0; + break; + case "OptimizePatchSizeForLargeFiles": + optimizePatchSizeForLargeFiles = (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)); + break; + default: + this.Core.UnexpectedAttribute(node, attrib); + break; + } + } + else + { + this.Core.ParseExtensionAttribute(node, attrib); + } + } + + if (patchId == null || patchId == "*") + { + // auto-generate at compile time, since this value gets dispersed to several locations + patchId = Common.GenerateGuid(); + } + this.activeName = patchId; + + if (null == this.activeName) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); + } + if (null == classification) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Classification")); + } + if (null == clientPatchId) + { + clientPatchId = String.Concat("_", new Guid(patchId).ToString("N", CultureInfo.InvariantCulture).ToUpper(CultureInfo.InvariantCulture)); + } + if (null == description) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Description")); + } + if (null == displayName) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "DisplayName")); + } + if (null == manufacturer) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Manufacturer")); + } + + this.Core.CreateActiveSection(this.activeName, SectionType.Patch, codepage, this.Context.CompilationId); + + foreach (var child in node.Elements()) + { + if (CompilerCore.WixNamespace == child.Name.Namespace) + { + switch (child.Name.LocalName) + { + case "PatchInformation": + this.ParsePatchInformationElement(child); + break; + case "Media": + this.ParseMediaElement(child, patchId); + break; + case "OptimizeCustomActions": + optimizeCA = this.ParseOptimizeCustomActionsElement(child); + break; + case "PatchFamily": + this.ParsePatchFamilyElement(child, ComplexReferenceParentType.Patch, patchId); + break; + case "PatchFamilyRef": + this.ParsePatchFamilyRefElement(child, ComplexReferenceParentType.Patch, patchId); + break; + case "PatchFamilyGroup": + this.ParsePatchFamilyGroupElement(child, ComplexReferenceParentType.Patch, patchId); + break; + case "PatchFamilyGroupRef": + this.ParsePatchFamilyGroupRefElement(child, ComplexReferenceParentType.Patch, patchId); + break; + case "PatchProperty": + this.ParsePatchPropertyElement(child, true); + break; + case "TargetProductCodes": + this.ParseTargetProductCodesElement(child); + break; + default: + this.Core.UnexpectedElement(node, child); + break; + } + } + else + { + this.Core.ParseExtensionElement(node, child); + } + } + + if (!this.Core.EncounteredError) + { + var tuple = new WixPatchIdTuple(sourceLineNumbers) + { + ProductCode = patchId, + ClientPatchId = clientPatchId, + OptimizePatchSizeForLargeFiles = optimizePatchSizeForLargeFiles, + ApiPatchingSymbolFlags = apiPatchingSymbolFlags + }; + + this.Core.AddTuple(tuple); + + if (allowRemoval) + { + this.AddMsiPatchMetadata(sourceLineNumbers, null, "AllowRemoval", allowRemoval ? "1" : "0"); + } + + if (null != classification) + { + this.AddMsiPatchMetadata(sourceLineNumbers, null, "Classification", classification); + } + + // always generate the CreationTimeUTC + { + this.AddMsiPatchMetadata(sourceLineNumbers, null, "CreationTimeUTC", DateTime.UtcNow.ToString("MM-dd-yy HH:mm", CultureInfo.InvariantCulture)); + } + + if (null != description) + { + this.AddMsiPatchMetadata(sourceLineNumbers, null, "Description", description); + } + + if (null != displayName) + { + this.AddMsiPatchMetadata(sourceLineNumbers, null, "DisplayName", displayName); + } + + if (null != manufacturer) + { + this.AddMsiPatchMetadata(sourceLineNumbers, null, "ManufacturerName", manufacturer); + } + + if (YesNoType.NotSet != minorUpdateTargetRTM) + { + this.AddMsiPatchMetadata(sourceLineNumbers, null, "MinorUpdateTargetRTM", YesNoType.Yes == minorUpdateTargetRTM ? "1" : "0"); + } + + if (null != moreInfoUrl) + { + this.AddMsiPatchMetadata(sourceLineNumbers, null, "MoreInfoURL", moreInfoUrl); + } + + if (CompilerConstants.IntegerNotSet != optimizeCA) + { + this.AddMsiPatchMetadata(sourceLineNumbers, null, "OptimizeCA", optimizeCA.ToString(CultureInfo.InvariantCulture)); + } + + if (YesNoType.NotSet != optimizedInstallMode) + { + this.AddMsiPatchMetadata(sourceLineNumbers, null, "OptimizedInstallMode", YesNoType.Yes == optimizedInstallMode ? "1" : "0"); + } + + if (null != targetProductName) + { + this.AddMsiPatchMetadata(sourceLineNumbers, null, "TargetProductName", targetProductName); + } + + if (null != comments) + { + this.AddMsiPatchMetadata(sourceLineNumbers, null, "Comments", comments); + } + } + // TODO: do something with versionMismatches and productMismatches + } + + /// + /// Parses the OptimizeCustomActions element. + /// + /// Element to parse. + /// The combined integer value for callers to store as appropriate. + private int ParseOptimizeCustomActionsElement(XElement node) + { + var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + var optimizeCA = OptimizeCA.None; + + foreach (var attrib in node.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "SkipAssignment": + if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + optimizeCA |= OptimizeCA.SkipAssignment; + } + break; + case "SkipImmediate": + if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + optimizeCA |= OptimizeCA.SkipImmediate; + } + break; + case "SkipDeferred": + if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + optimizeCA |= OptimizeCA.SkipDeferred; + } + break; + default: + this.Core.UnexpectedAttribute(node, attrib); + break; + } + } + else + { + this.Core.ParseExtensionAttribute(node, attrib); + } + } + + return (int)optimizeCA; + } + + /// + /// Parses a PatchFamily element. + /// + /// The element to parse. + private void ParsePatchFamilyElement(XElement node, ComplexReferenceParentType parentType, string parentId) + { + var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + Identifier id = null; + string productCode = null; + string version = null; + var attributes = 0; + + foreach (var attrib in node.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib); + break; + case "ProductCode": + productCode = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false); + break; + case "Version": + version = this.Core.GetAttributeVersionValue(sourceLineNumbers, attrib); + break; + case "Supersede": + if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + attributes |= 0x1; + } + break; + default: + this.Core.UnexpectedAttribute(node, attrib); + break; + } + } + else + { + this.Core.ParseExtensionAttribute(node, attrib); + } + } + + if (null == id) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); + id = Identifier.Invalid; + } + + if (String.IsNullOrEmpty(version)) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Version")); + } + else if (!CompilerCore.IsValidProductVersion(version)) + { + this.Core.Write(ErrorMessages.InvalidProductVersion(sourceLineNumbers, version)); + } + + // find unexpected child elements + foreach (var child in node.Elements()) + { + if (CompilerCore.WixNamespace == child.Name.Namespace) + { + switch (child.Name.LocalName) + { + case "All": + this.ParseAllElement(child); + break; + case "BinaryRef": + this.ParsePatchChildRefElement(child, "Binary"); + break; + case "ComponentRef": + this.ParsePatchChildRefElement(child, "Component"); + break; + case "CustomActionRef": + this.ParsePatchChildRefElement(child, "CustomAction"); + break; + case "DirectoryRef": + this.ParsePatchChildRefElement(child, "Directory"); + break; + case "DigitalCertificateRef": + this.ParsePatchChildRefElement(child, "MsiDigitalCertificate"); + break; + case "FeatureRef": + this.ParsePatchChildRefElement(child, "Feature"); + break; + case "IconRef": + this.ParsePatchChildRefElement(child, "Icon"); + break; + case "PropertyRef": + this.ParsePatchChildRefElement(child, "Property"); + break; + case "UIRef": + this.ParsePatchChildRefElement(child, "WixUI"); + break; + default: + this.Core.UnexpectedElement(node, child); + break; + } + } + else + { + this.Core.ParseExtensionElement(node, child); + } + } + + + if (!this.Core.EncounteredError) + { + var tuple = new MsiPatchSequenceTuple(sourceLineNumbers) + { + PatchFamily = id.Id, + ProductCode = productCode, + Sequence = version, + Attributes = attributes + }; + + this.Core.AddTuple(tuple); + + if (ComplexReferenceParentType.Unknown != parentType) + { + this.Core.CreateComplexReference(sourceLineNumbers, parentType, parentId, null, ComplexReferenceChildType.PatchFamily, id.Id, ComplexReferenceParentType.Patch == parentType); + } + } + } + + /// + /// Parses a PatchFamilyGroup element. + /// + /// Element to parse. + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")] + private void ParsePatchFamilyGroupElement(XElement node, ComplexReferenceParentType parentType, string parentId) + { + var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + Identifier id = null; + + foreach (var attrib in node.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib); + break; + default: + this.Core.UnexpectedAttribute(node, attrib); + break; + } + } + else + { + this.Core.ParseExtensionAttribute(node, attrib); + } + } + + if (null == id) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); + id = Identifier.Invalid; + } + + foreach (var child in node.Elements()) + { + if (CompilerCore.WixNamespace == child.Name.Namespace) + { + switch (child.Name.LocalName) + { + case "PatchFamily": + this.ParsePatchFamilyElement(child, ComplexReferenceParentType.PatchFamilyGroup, id.Id); + break; + case "PatchFamilyRef": + this.ParsePatchFamilyRefElement(child, ComplexReferenceParentType.PatchFamilyGroup, id.Id); + break; + case "PatchFamilyGroupRef": + this.ParsePatchFamilyGroupRefElement(child, ComplexReferenceParentType.PatchFamilyGroup, id.Id); + break; + default: + this.Core.UnexpectedElement(node, child); + break; + } + } + else + { + this.Core.ParseExtensionElement(node, child); + } + } + + if (!this.Core.EncounteredError) + { + this.Core.AddTuple(new WixPatchFamilyGroupTuple(sourceLineNumbers, id)); + + //Add this PatchFamilyGroup and its parent in WixGroup. + this.Core.CreateWixGroupRow(sourceLineNumbers, parentType, parentId, ComplexReferenceChildType.PatchFamilyGroup, id.Id); + } + } + + /// + /// Parses a PatchFamilyGroup reference element. + /// + /// Element to parse. + /// The type of parent. + /// Identifier of parent element. + private void ParsePatchFamilyGroupRefElement(XElement node, ComplexReferenceParentType parentType, string parentId) + { + Debug.Assert(ComplexReferenceParentType.PatchFamilyGroup == parentType || ComplexReferenceParentType.Patch == parentType); + + var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + string id = null; + + foreach (var attrib in node.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); + this.Core.CreateSimpleReference(sourceLineNumbers, "WixPatchFamilyGroup", id); + break; + default: + this.Core.UnexpectedAttribute(node, attrib); + break; + } + } + else + { + this.Core.ParseExtensionAttribute(node, attrib); + } + } + + if (null == id) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); + } + + this.Core.ParseForExtensionElements(node); + + if (!this.Core.EncounteredError) + { + this.Core.CreateComplexReference(sourceLineNumbers, parentType, parentId, null, ComplexReferenceChildType.PatchFamilyGroup, id, true); + } + } + + /// + /// Parses a TargetProductCodes element. + /// + /// The element to parse. + private void ParseTargetProductCodesElement(XElement node) + { + var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + var replace = false; + var targetProductCodes = new List(); + + foreach (var attrib in node.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Replace": + replace = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; + default: + this.Core.UnexpectedAttribute(node, attrib); + break; + } + } + else + { + this.Core.ParseExtensionAttribute(node, attrib); + } + } + + foreach (var child in node.Elements()) + { + if (CompilerCore.WixNamespace == child.Name.Namespace) + { + switch (child.Name.LocalName) + { + case "TargetProductCode": + var id = this.ParseTargetProductCodeElement(child); + if (0 == String.CompareOrdinal("*", id)) + { + this.Core.Write(ErrorMessages.IllegalAttributeValueWhenNested(sourceLineNumbers, child.Name.LocalName, "Id", id, node.Name.LocalName)); + } + else + { + targetProductCodes.Add(id); + } + break; + default: + this.Core.UnexpectedElement(node, child); + break; + } + } + else + { + this.Core.ParseExtensionElement(node, child); + } + } + + if (!this.Core.EncounteredError) + { + // By default, target ProductCodes should be added. + if (!replace) + { + this.Core.AddTuple(new WixPatchTargetTuple(sourceLineNumbers) + { + ProductCode = "*" + }); + } + + foreach (var targetProductCode in targetProductCodes) + { + this.Core.AddTuple(new WixPatchTargetTuple(sourceLineNumbers) + { + ProductCode = targetProductCode + }); + } + } + } + + private void AddMsiPatchMetadata(SourceLineNumber sourceLineNumbers, string company, string property, string value) + { + this.Core.AddTuple(new MsiPatchMetadataTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, company, property)) + { + Company = company, + Property = property, + Value = value + }); + } + } +} diff --git a/src/WixToolset.Core/Compiler_PatchCreation.cs b/src/WixToolset.Core/Compiler_PatchCreation.cs new file mode 100644 index 00000000..42cdf374 --- /dev/null +++ b/src/WixToolset.Core/Compiler_PatchCreation.cs @@ -0,0 +1,1313 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. + +namespace WixToolset.Core +{ + using System; + using System.Collections.Generic; + using System.Globalization; + using System.Xml.Linq; + using WixToolset.Data; + using WixToolset.Data.Tuples; + using WixToolset.Extensibility; + + /// + /// Compiler of the WiX toolset. + /// + internal partial class Compiler : ICompiler + { + /// + /// Parses a patch creation element. + /// + /// The element to parse. + private void ParsePatchCreationElement(XElement node) + { + var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + var clean = true; // Default is to clean + var codepage = 0; + string outputPath = null; + var productMismatches = false; + var replaceGuids = String.Empty; + string sourceList = null; + string symbolFlags = null; + var targetProducts = String.Empty; + var versionMismatches = false; + var wholeFiles = false; + + foreach (var attrib in node.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + this.activeName = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false); + break; + case "AllowMajorVersionMismatches": + versionMismatches = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; + case "AllowProductCodeMismatches": + productMismatches = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; + case "CleanWorkingFolder": + clean = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; + case "Codepage": + codepage = this.Core.GetAttributeCodePageValue(sourceLineNumbers, attrib); + break; + case "OutputPath": + outputPath = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "SourceList": + sourceList = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "SymbolFlags": + symbolFlags = String.Format(CultureInfo.InvariantCulture, "0x{0:x8}", this.Core.GetAttributeLongValue(sourceLineNumbers, attrib, 0, UInt32.MaxValue)); + break; + case "WholeFilesOnly": + wholeFiles = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; + default: + this.Core.UnexpectedAttribute(node, attrib); + break; + } + } + else + { + this.Core.ParseExtensionAttribute(node, attrib); + } + } + + if (null == this.activeName) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); + } + + this.Core.CreateActiveSection(this.activeName, SectionType.PatchCreation, codepage, this.Context.CompilationId); + + foreach (var child in node.Elements()) + { + if (CompilerCore.WixNamespace == child.Name.Namespace) + { + switch (child.Name.LocalName) + { + case "Family": + this.ParseFamilyElement(child); + break; + case "PatchInformation": + this.ParsePatchInformationElement(child); + break; + case "PatchMetadata": + this.ParsePatchMetadataElement(child); + break; + case "PatchProperty": + this.ParsePatchPropertyElement(child, false); + break; + case "PatchSequence": + this.ParsePatchSequenceElement(child); + break; + case "ReplacePatch": + replaceGuids = String.Concat(replaceGuids, this.ParseReplacePatchElement(child)); + break; + case "TargetProductCode": + var targetProduct = this.ParseTargetProductCodeElement(child); + if (0 < targetProducts.Length) + { + targetProducts = String.Concat(targetProducts, ";"); + } + targetProducts = String.Concat(targetProducts, targetProduct); + break; + default: + this.Core.UnexpectedElement(node, child); + break; + } + } + else + { + this.Core.ParseExtensionElement(node, child); + } + } + + this.AddPrivateProperty(sourceLineNumbers, "PatchGUID", this.activeName); + this.AddPrivateProperty(sourceLineNumbers, "AllowProductCodeMismatches", productMismatches ? "1" : "0"); + this.AddPrivateProperty(sourceLineNumbers, "AllowProductVersionMajorMismatches", versionMismatches ? "1" : "0"); + this.AddPrivateProperty(sourceLineNumbers, "DontRemoveTempFolderWhenFinished", clean ? "0" : "1"); + this.AddPrivateProperty(sourceLineNumbers, "IncludeWholeFilesOnly", wholeFiles ? "1" : "0"); + + if (null != symbolFlags) + { + this.AddPrivateProperty(sourceLineNumbers, "ApiPatchingSymbolFlags", symbolFlags); + } + + if (0 < replaceGuids.Length) + { + this.AddPrivateProperty(sourceLineNumbers, "ListOfPatchGUIDsToReplace", replaceGuids); + } + + if (0 < targetProducts.Length) + { + this.AddPrivateProperty(sourceLineNumbers, "ListOfTargetProductCodes", targetProducts); + } + + if (null != outputPath) + { + this.AddPrivateProperty(sourceLineNumbers, "PatchOutputPath", outputPath); + } + + if (null != sourceList) + { + this.AddPrivateProperty(sourceLineNumbers, "PatchSourceList", sourceList); + } + } + + /// + /// Parses a family element. + /// + /// The element to parse. + private void ParseFamilyElement(XElement node) + { + var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + var diskId = CompilerConstants.IntegerNotSet; + string diskPrompt = null; + string mediaSrcProp = null; + string name = null; + var sequenceStart = CompilerConstants.IntegerNotSet; + string volumeLabel = null; + + foreach (var attrib in node.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "DiskId": + diskId = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, Int16.MaxValue); + break; + case "DiskPrompt": + diskPrompt = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "MediaSrcProp": + mediaSrcProp = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Name": + name = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "SequenceStart": + sequenceStart = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, Int32.MaxValue); + break; + case "VolumeLabel": + volumeLabel = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + default: + this.Core.UnexpectedAttribute(node, attrib); + break; + } + } + else + { + this.Core.ParseExtensionAttribute(node, attrib); + } + } + + if (null == name) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Name")); + } + else if (0 < name.Length) + { + if (8 < name.Length) // check the length + { + this.Core.Write(ErrorMessages.FamilyNameTooLong(sourceLineNumbers, node.Name.LocalName, "Name", name, name.Length)); + } + else // check for illegal characters + { + foreach (var character in name) + { + if (!Char.IsLetterOrDigit(character) && '_' != character) + { + this.Core.Write(ErrorMessages.IllegalFamilyName(sourceLineNumbers, node.Name.LocalName, "Name", name)); + } + } + } + } + + foreach (var child in node.Elements()) + { + if (CompilerCore.WixNamespace == child.Name.Namespace) + { + switch (child.Name.LocalName) + { + case "UpgradeImage": + this.ParseUpgradeImageElement(child, name); + break; + case "ExternalFile": + this.ParseExternalFileElement(child, name); + break; + case "ProtectFile": + this.ParseProtectFileElement(child, name); + break; + default: + this.Core.UnexpectedElement(node, child); + break; + } + } + else + { + this.Core.ParseExtensionElement(node, child); + } + } + + if (!this.Core.EncounteredError) + { + var tuple = new ImageFamiliesTuple(sourceLineNumbers) + { + Family = name, + MediaSrcPropName = mediaSrcProp, + DiskPrompt = diskPrompt, + VolumeLabel = volumeLabel + }; + + if (CompilerConstants.IntegerNotSet != diskId) + { + tuple.MediaDiskId = diskId; + } + + if (CompilerConstants.IntegerNotSet != sequenceStart) + { + tuple.FileSequenceStart = sequenceStart; + } + + this.Core.AddTuple(tuple); + } + } + + /// + /// Parses an upgrade image element. + /// + /// The element to parse. + /// The family for this element. + private void ParseUpgradeImageElement(XElement node, string family) + { + var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + string sourceFile = null; + string sourcePatch = null; + var symbols = new List(); + string upgrade = null; + + foreach (var attrib in node.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + upgrade = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + if (13 < upgrade.Length) + { + this.Core.Write(ErrorMessages.IdentifierTooLongError(sourceLineNumbers, node.Name.LocalName, "Id", upgrade, 13)); + } + break; + case "SourceFile": + case "src": + if (null != sourceFile) + { + this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, "src", "SourceFile")); + } + + if ("src" == attrib.Name.LocalName) + { + this.Core.Write(WarningMessages.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "SourceFile")); + } + sourceFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "SourcePatch": + case "srcPatch": + if (null != sourcePatch) + { + this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, "srcPatch", "SourcePatch")); + } + + if ("srcPatch" == attrib.Name.LocalName) + { + this.Core.Write(WarningMessages.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "SourcePatch")); + } + sourcePatch = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + default: + this.Core.UnexpectedAttribute(node, attrib); + break; + } + } + else + { + this.Core.ParseExtensionAttribute(node, attrib); + } + } + + if (null == upgrade) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); + } + + if (null == sourceFile) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "SourceFile")); + } + + foreach (var child in node.Elements()) + { + if (CompilerCore.WixNamespace == child.Name.Namespace) + { + switch (child.Name.LocalName) + { + case "SymbolPath": + symbols.Add(this.ParseSymbolPathElement(child)); + break; + case "TargetImage": + this.ParseTargetImageElement(child, upgrade, family); + break; + case "UpgradeFile": + this.ParseUpgradeFileElement(child, upgrade); + break; + default: + this.Core.UnexpectedElement(node, child); + break; + } + } + else + { + this.Core.ParseExtensionElement(node, child); + } + } + + if (!this.Core.EncounteredError) + { + this.Core.AddTuple(new UpgradedImagesTuple(sourceLineNumbers) + { + Upgraded = upgrade, + MsiPath = sourceFile, + PatchMsiPath = sourcePatch, + SymbolPaths = String.Join(";", symbols), + Family = family + }); + } + } + + /// + /// Parses an upgrade file element. + /// + /// The element to parse. + /// The upgrade key for this element. + private void ParseUpgradeFileElement(XElement node, string upgrade) + { + var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + var allowIgnoreOnError = false; + string file = null; + var ignore = false; + var symbols = new List(); + var wholeFile = false; + + foreach (var attrib in node.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "AllowIgnoreOnError": + allowIgnoreOnError = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; + case "File": + file = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Ignore": + ignore = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; + case "WholeFile": + wholeFile = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; + default: + this.Core.UnexpectedAttribute(node, attrib); + break; + } + } + else + { + this.Core.ParseExtensionAttribute(node, attrib); + } + } + + if (null == file) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "File")); + } + + foreach (var child in node.Elements()) + { + if (CompilerCore.WixNamespace == child.Name.Namespace) + { + switch (child.Name.LocalName) + { + case "SymbolPath": + symbols.Add(this.ParseSymbolPathElement(child)); + break; + default: + this.Core.UnexpectedElement(node, child); + break; + } + } + else + { + this.Core.ParseExtensionElement(node, child); + } + } + + if (!this.Core.EncounteredError) + { + if (ignore) + { + this.Core.AddTuple(new UpgradedFilesToIgnoreTuple(sourceLineNumbers) + { + Upgraded = upgrade, + FTK = file + }); + } + else + { + this.Core.AddTuple(new UpgradedFiles_OptionalDataTuple(sourceLineNumbers) + { + Upgraded = upgrade, + FTK = file, + SymbolPaths = String.Join(";", symbols), + AllowIgnoreOnPatchError = allowIgnoreOnError, + IncludeWholeFile = wholeFile + }); + } + } + } + + /// + /// Parses a target image element. + /// + /// The element to parse. + /// The upgrade key for this element. + /// The family key for this element. + private void ParseTargetImageElement(XElement node, string upgrade, string family) + { + var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + var ignore = false; + var order = CompilerConstants.IntegerNotSet; + string sourceFile = null; + string symbols = null; + string target = null; + string validation = null; + + foreach (var attrib in node.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + target = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + if (target.Length > 13) + { + this.Core.Write(ErrorMessages.IdentifierTooLongError(sourceLineNumbers, node.Name.LocalName, "Id", target, 13)); + } + break; + case "IgnoreMissingFiles": + ignore = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; + case "Order": + order = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, Int32.MinValue + 2, Int32.MaxValue); + break; + case "SourceFile": + case "src": + if (null != sourceFile) + { + this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, "src", "SourceFile")); + } + + if ("src" == attrib.Name.LocalName) + { + this.Core.Write(WarningMessages.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "SourceFile")); + } + sourceFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Validation": + validation = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + default: + this.Core.UnexpectedAttribute(node, attrib); + break; + } + } + else + { + this.Core.ParseExtensionAttribute(node, attrib); + } + } + + if (null == target) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); + } + + if (null == sourceFile) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "SourceFile")); + } + + if (CompilerConstants.IntegerNotSet == order) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Order")); + } + + foreach (var child in node.Elements()) + { + if (CompilerCore.WixNamespace == child.Name.Namespace) + { + switch (child.Name.LocalName) + { + case "SymbolPath": + if (null != symbols) + { + symbols = String.Concat(symbols, ";", this.ParseSymbolPathElement(child)); + } + else + { + symbols = this.ParseSymbolPathElement(child); + } + break; + case "TargetFile": + this.ParseTargetFileElement(child, target, family); + break; + default: + this.Core.UnexpectedElement(node, child); + break; + } + } + else + { + this.Core.ParseExtensionElement(node, child); + } + } + + if (!this.Core.EncounteredError) + { + this.Core.AddTuple(new TargetImagesTuple(sourceLineNumbers) + { + Target = target, + MsiPath = sourceFile, + SymbolPaths = symbols, + Upgraded = upgrade, + Order = order, + ProductValidateFlags = validation, + IgnoreMissingSrcFiles = ignore + }); + } + } + + /// + /// Parses an upgrade file element. + /// + /// The element to parse. + /// The upgrade key for this element. + /// The family key for this element. + private void ParseTargetFileElement(XElement node, string target, string family) + { + var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + string file = null; + string ignoreLengths = null; + string ignoreOffsets = null; + string protectLengths = null; + string protectOffsets = null; + string symbols = null; + + foreach (var attrib in node.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + file = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + default: + this.Core.UnexpectedAttribute(node, attrib); + break; + } + } + else + { + this.Core.ParseExtensionAttribute(node, attrib); + } + } + + if (null == file) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id")); + } + + foreach (var child in node.Elements()) + { + if (CompilerCore.WixNamespace == child.Name.Namespace) + { + switch (child.Name.LocalName) + { + case "IgnoreRange": + this.ParseRangeElement(child, ref ignoreOffsets, ref ignoreLengths); + break; + case "ProtectRange": + this.ParseRangeElement(child, ref protectOffsets, ref protectLengths); + break; + case "SymbolPath": + symbols = this.ParseSymbolPathElement(child); + break; + default: + this.Core.UnexpectedElement(node, child); + break; + } + } + else + { + this.Core.ParseExtensionElement(node, child); + } + } + + if (!this.Core.EncounteredError) + { + var tuple = new TargetFiles_OptionalDataTuple(sourceLineNumbers) + { + Target = target, + FTK = file, + SymbolPaths = symbols, + IgnoreOffsets = ignoreOffsets, + IgnoreLengths = ignoreLengths + }; + + this.Core.AddTuple(tuple); + + if (null != protectOffsets) + { + tuple.RetainOffsets = protectOffsets; + + this.Core.AddTuple(new FamilyFileRangesTuple(sourceLineNumbers) + { + Family = family, + FTK = file, + RetainOffsets = protectOffsets, + RetainLengths = protectLengths + }); + } + } + } + + /// + /// Parses an external file element. + /// + /// The element to parse. + /// The family for this element. + private void ParseExternalFileElement(XElement node, string family) + { + var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + string file = null; + string ignoreLengths = null; + string ignoreOffsets = null; + var order = CompilerConstants.IntegerNotSet; + string protectLengths = null; + string protectOffsets = null; + string source = null; + string symbols = null; + + foreach (var attrib in node.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "File": + file = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Order": + order = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, Int32.MinValue + 2, Int32.MaxValue); + break; + case "Source": + case "src": + if (null != source) + { + this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, "src", "Source")); + } + + if ("src" == attrib.Name.LocalName) + { + this.Core.Write(WarningMessages.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "Source")); + } + source = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + default: + this.Core.UnexpectedAttribute(node, attrib); + break; + } + } + else + { + this.Core.ParseExtensionAttribute(node, attrib); + } + } + + if (null == file) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "File")); + } + + if (null == source) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Source")); + } + + if (CompilerConstants.IntegerNotSet == order) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Order")); + } + + foreach (var child in node.Elements()) + { + if (CompilerCore.WixNamespace == child.Name.Namespace) + { + switch (child.Name.LocalName) + { + case "IgnoreRange": + this.ParseRangeElement(child, ref ignoreOffsets, ref ignoreLengths); + break; + case "ProtectRange": + this.ParseRangeElement(child, ref protectOffsets, ref protectLengths); + break; + case "SymbolPath": + symbols = this.ParseSymbolPathElement(child); + break; + default: + this.Core.UnexpectedElement(node, child); + break; + } + } + else + { + this.Core.ParseExtensionElement(node, child); + } + } + + if (!this.Core.EncounteredError) + { + var tuple = new ExternalFilesTuple(sourceLineNumbers) + { + Family = family, + FTK = file, + FilePath = source, + SymbolPaths = symbols, + IgnoreOffsets = ignoreOffsets, + IgnoreLengths = ignoreLengths + }; + + if (null != protectOffsets) + { + tuple.RetainOffsets = protectOffsets; + } + + if (CompilerConstants.IntegerNotSet != order) + { + tuple.Order = order; + } + + this.Core.AddTuple(tuple); + + if (null != protectOffsets) + { + this.Core.AddTuple(new FamilyFileRangesTuple(sourceLineNumbers) + { + Family = family, + FTK = file, + RetainOffsets = protectOffsets, + RetainLengths = protectLengths + }); + } + } + } + + /// + /// Parses a protect file element. + /// + /// The element to parse. + /// The family for this element. + private void ParseProtectFileElement(XElement node, string family) + { + var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + string file = null; + string protectLengths = null; + string protectOffsets = null; + + foreach (var attrib in node.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "File": + file = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + default: + this.Core.UnexpectedAttribute(node, attrib); + break; + } + } + else + { + this.Core.ParseExtensionAttribute(node, attrib); + } + } + + if (null == file) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "File")); + } + + foreach (var child in node.Elements()) + { + if (CompilerCore.WixNamespace == child.Name.Namespace) + { + switch (child.Name.LocalName) + { + case "ProtectRange": + this.ParseRangeElement(child, ref protectOffsets, ref protectLengths); + break; + default: + this.Core.UnexpectedElement(node, child); + break; + } + } + else + { + this.Core.ParseExtensionElement(node, child); + } + } + + if (null == protectOffsets || null == protectLengths) + { + this.Core.Write(ErrorMessages.ExpectedElement(sourceLineNumbers, node.Name.LocalName, "ProtectRange")); + } + + if (!this.Core.EncounteredError) + { + this.Core.AddTuple(new FamilyFileRangesTuple(sourceLineNumbers) + { + Family = family, + FTK = file, + RetainOffsets = protectOffsets, + RetainLengths = protectLengths + }); + } + } + + /// + /// Parses a range element (ProtectRange, IgnoreRange, etc). + /// + /// The element to parse. + /// Reference to the offsets string. + /// Reference to the lengths string. + private void ParseRangeElement(XElement node, ref string offsets, ref string lengths) + { + var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + string length = null; + string offset = null; + + foreach (var attrib in node.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Length": + length = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Offset": + offset = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + default: + this.Core.UnexpectedAttribute(node, attrib); + break; + } + } + else + { + this.Core.ParseExtensionAttribute(node, attrib); + } + } + + if (null == length) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Length")); + } + + if (null == offset) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Offset")); + } + + this.Core.ParseForExtensionElements(node); + + if (null != lengths) + { + lengths = String.Concat(lengths, ",", length); + } + else + { + lengths = length; + } + + if (null != offsets) + { + offsets = String.Concat(offsets, ",", offset); + } + else + { + offsets = offset; + } + } + + /// + /// Parses a patch metadata element. + /// + /// Element to parse. + private void ParsePatchMetadataElement(XElement node) + { + var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + var allowRemoval = YesNoType.NotSet; + string classification = null; + string creationTimeUtc = null; + string description = null; + string displayName = null; + string manufacturerName = null; + string minorUpdateTargetRTM = null; + string moreInfoUrl = null; + var optimizeCA = CompilerConstants.IntegerNotSet; + var optimizedInstallMode = YesNoType.NotSet; + string targetProductName = null; + + foreach (var attrib in node.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "AllowRemoval": + allowRemoval = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; + case "Classification": + classification = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "CreationTimeUTC": + creationTimeUtc = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Description": + description = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "DisplayName": + displayName = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "ManufacturerName": + manufacturerName = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "MinorUpdateTargetRTM": + minorUpdateTargetRTM = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "MoreInfoURL": + moreInfoUrl = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "OptimizedInstallMode": + optimizedInstallMode = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); + break; + case "TargetProductName": + targetProductName = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + default: + this.Core.UnexpectedAttribute(node, attrib); + break; + } + } + else + { + this.Core.ParseExtensionAttribute(node, attrib); + } + } + + if (YesNoType.NotSet == allowRemoval) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "AllowRemoval")); + } + + if (null == classification) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Classification")); + } + + if (null == description) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Description")); + } + + if (null == displayName) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "DisplayName")); + } + + if (null == manufacturerName) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "ManufacturerName")); + } + + if (null == moreInfoUrl) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "MoreInfoURL")); + } + + if (null == targetProductName) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "TargetProductName")); + } + + foreach (var child in node.Elements()) + { + if (CompilerCore.WixNamespace == child.Name.Namespace) + { + switch (child.Name.LocalName) + { + case "CustomProperty": + this.ParseCustomPropertyElement(child); + break; + case "OptimizeCustomActions": + optimizeCA = this.ParseOptimizeCustomActionsElement(child); + break; + default: + this.Core.UnexpectedElement(node, child); + break; + } + } + else + { + this.Core.ParseExtensionElement(node, child); + } + } + + if (!this.Core.EncounteredError) + { + if (YesNoType.NotSet != allowRemoval) + { + this.AddPatchMetadata(sourceLineNumbers, null, "AllowRemoval", YesNoType.Yes == allowRemoval ? "1" : "0"); + } + + if (null != classification) + { + this.AddPatchMetadata(sourceLineNumbers, null, "Classification", classification); + } + + if (null != creationTimeUtc) + { + this.AddPatchMetadata(sourceLineNumbers, null, "CreationTimeUTC", creationTimeUtc); + } + + if (null != description) + { + this.AddPatchMetadata(sourceLineNumbers, null, "Description", description); + } + + if (null != displayName) + { + this.AddPatchMetadata(sourceLineNumbers, null, "DisplayName", displayName); + } + + if (null != manufacturerName) + { + this.AddPatchMetadata(sourceLineNumbers, null, "ManufacturerName", manufacturerName); + } + + if (null != minorUpdateTargetRTM) + { + this.AddPatchMetadata(sourceLineNumbers, null, "MinorUpdateTargetRTM", minorUpdateTargetRTM); + } + + if (null != moreInfoUrl) + { + this.AddPatchMetadata(sourceLineNumbers, null, "MoreInfoURL", moreInfoUrl); + } + + if (CompilerConstants.IntegerNotSet != optimizeCA) + { + this.AddPatchMetadata(sourceLineNumbers, null, "OptimizeCA", optimizeCA.ToString(CultureInfo.InvariantCulture)); + } + + if (YesNoType.NotSet != optimizedInstallMode) + { + this.AddPatchMetadata(sourceLineNumbers, null, "OptimizedInstallMode", YesNoType.Yes == optimizedInstallMode ? "1" : "0"); + } + + if (null != targetProductName) + { + this.AddPatchMetadata(sourceLineNumbers, null, "TargetProductName", targetProductName); + } + } + } + + /// + /// Parses a custom property element for the PatchMetadata table. + /// + /// Element to parse. + private void ParseCustomPropertyElement(XElement node) + { + var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + string company = null; + string property = null; + string value = null; + + foreach (var attrib in node.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Company": + company = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Property": + property = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Value": + value = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + default: + this.Core.UnexpectedAttribute(node, attrib); + break; + } + } + else + { + this.Core.ParseExtensionAttribute(node, attrib); + } + } + + if (null == company) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Company")); + } + + if (null == property) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Property")); + } + + if (null == value) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Value")); + } + + this.Core.ParseForExtensionElements(node); + + if (!this.Core.EncounteredError) + { + this.AddPatchMetadata(sourceLineNumbers, company, property, value); + } + } + + /// + /// Parses a patch sequence element. + /// + /// The element to parse. + private void ParsePatchSequenceElement(XElement node) + { + var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); + string family = null; + string target = null; + string sequence = null; + var attributes = 0; + + foreach (var attrib in node.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "PatchFamily": + family = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); + break; + case "ProductCode": + if (null != target) + { + this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "Target", "TargetImage")); + } + target = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false); + break; + case "Target": + if (null != target) + { + this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "TargetImage", "ProductCode")); + } + this.Core.Write(WarningMessages.DeprecatedPatchSequenceTargetAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName)); + target = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "TargetImage": + if (null != target) + { + this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "Target", "ProductCode")); + } + target = this.Core.GetAttributeValue(sourceLineNumbers, attrib); + this.Core.CreateSimpleReference(sourceLineNumbers, "TargetImages", target); + break; + case "Sequence": + sequence = this.Core.GetAttributeVersionValue(sourceLineNumbers, attrib); + break; + case "Supersede": + if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + attributes |= 0x1; + } + break; + default: + this.Core.UnexpectedAttribute(node, attrib); + break; + } + } + else + { + this.Core.ParseExtensionAttribute(node, attrib); + } + } + + if (null == family) + { + this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "PatchFamily")); + } + + this.Core.ParseForExtensionElements(node); + + if (!this.Core.EncounteredError) + { + var tuple = new PatchSequenceTuple(sourceLineNumbers) + { + PatchFamily = family, + Target = target, + Sequence = sequence, + Supersede = attributes + }; + + this.Core.AddTuple(tuple); + } + } + + private void AddPatchMetadata(SourceLineNumber sourceLineNumbers, string company, string property, string value) + { + this.Core.AddTuple(new PatchMetadataTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, company, property)) + { + Company = company, + Property = property, + Value = value + }); + } + } +} diff --git a/src/WixToolset.Core/Compiler_UI.cs b/src/WixToolset.Core/Compiler_UI.cs index fddb9061..24398895 100644 --- a/src/WixToolset.Core/Compiler_UI.cs +++ b/src/WixToolset.Core/Compiler_UI.cs @@ -120,8 +120,10 @@ namespace WixToolset.Core // the following are available indentically under the UI and Product elements for document organization use only case "AdminUISequence": + this.ParseSequenceElement(child, SequenceTable.AdminUISequence); + break; case "InstallUISequence": - this.ParseSequenceElement(child, child.Name.LocalName); + this.ParseSequenceElement(child, SequenceTable.InstallUISequence); break; case "Binary": this.ParseBinaryElement(child); @@ -149,7 +151,8 @@ namespace WixToolset.Core if (null != id && !this.Core.EncounteredError) { - this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixUI, id); + var tuple = new WixUITuple(sourceLineNumbers, id); + this.Core.AddTuple(tuple); } } @@ -160,7 +163,7 @@ namespace WixToolset.Core /// Table to add row to. /// Identifier of property referred to by list item. /// Relative order of list items. - private void ParseListItemElement(XElement node, TupleDefinitionType tableName, string property, ref int order) + private void ParseListItemElement(XElement node, TupleDefinitionType tupleType, string property, ref int order) { var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); string icon = null; @@ -174,7 +177,7 @@ namespace WixToolset.Core switch (attrib.Name.LocalName) { case "Icon": - if (TupleDefinitionType.ListView == tableName) + if (TupleDefinitionType.ListView == tupleType) { icon = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); this.Core.CreateSimpleReference(sourceLineNumbers, "Binary", icon); @@ -210,14 +213,14 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, tableName); - row.Set(0, property); - row.Set(1, ++order); - row.Set(2, value); - row.Set(3, text); + var tuple = this.Core.CreateTuple(sourceLineNumbers, tupleType); + tuple.Set(0, property); + tuple.Set(1, ++order); + tuple.Set(2, value); + tuple.Set(3, text); if (null != icon) { - row.Set(4, icon); + tuple.Set(4, icon); } } } @@ -335,19 +338,21 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.RadioButton); - row.Set(0, property); - row.Set(1, ++order); - row.Set(2, value); - row.Set(3, x); - row.Set(4, y); - row.Set(5, width); - row.Set(6, height); - row.Set(7, text); - if (null != tooltip || null != help) + var tuple = new RadioButtonTuple(sourceLineNumbers) { - row.Set(8, String.Concat(tooltip, "|", help)); - } + Property = property, + Order = ++order, + Value = value, + Text = text, + Help = (null != tooltip || null != help) ? String.Concat(tooltip, "|", help) : null + }; + + tuple.Set((int)RadioButtonTupleFields.X, x); + tuple.Set((int)RadioButtonTupleFields.Y, y); + tuple.Set((int)RadioButtonTupleFields.Width, width); + tuple.Set((int)RadioButtonTupleFields.Height, height); + + this.Core.AddTuple(tuple); } return type; @@ -481,10 +486,14 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Billboard, id); - row.Set(1, feature); - row.Set(2, action); - row.Set(3, order); + var tuple = new BillboardTuple(sourceLineNumbers, id) + { + Feature_ = feature, + Action = action, + Ordering = order + }; + + this.Core.AddTuple(tuple); } } @@ -494,7 +503,7 @@ namespace WixToolset.Core /// Element to parse. /// Table referred to by control group. /// Expected child elements. - private void ParseControlGroupElement(XElement node, TupleDefinitionType tableName, string childTag) + private void ParseControlGroupElement(XElement node, TupleDefinitionType tupleType, string childTag) { var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); var order = 0; @@ -537,7 +546,7 @@ namespace WixToolset.Core switch (child.Name.LocalName) { case "ListItem": - this.ParseListItemElement(child, tableName, property, ref order); + this.ParseListItemElement(child, tupleType, property, ref order); break; case "Property": this.ParsePropertyElement(child); @@ -668,10 +677,14 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ActionText); - row.Set(0, action); - row.Set(1, Common.GetInnerText(node)); - row.Set(2, template); + var tuple = new ActionTextTuple(sourceLineNumbers) + { + Action = action, + Description = Common.GetInnerText(node), + Template = template + }; + + this.Core.AddTuple(tuple); } } @@ -716,8 +729,12 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.UIText, id); - row.Set(1, text); + var tuple = new UITextTuple(sourceLineNumbers, id) + { + Text = text, + }; + + this.Core.AddTuple(tuple); } } @@ -1654,13 +1671,17 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ControlEvent); - row.Set(0, dialog); - row.Set(1, control); - row.Set(2, (null != controlEvent ? controlEvent : property)); - row.Set(3, argument); - row.Set(4, condition); - row.Set(5, order); + var tuple = new ControlEventTuple(sourceLineNumbers) + { + Dialog_ = dialog, + Control_ = control, + Event = controlEvent ?? property, + Argument = argument, + Condition = condition, + Ordering = order + }; + + this.Core.AddTuple(tuple); } if ("DoAction" == controlEvent && null != argument) @@ -1719,11 +1740,15 @@ namespace WixToolset.Core if (!this.Core.EncounteredError) { - var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.EventMapping); - row.Set(0, dialog); - row.Set(1, control); - row.Set(2, eventMapping); - row.Set(3, controlAttribute); + var tuple = new EventMappingTuple(sourceLineNumbers) + { + Dialog_ = dialog, + Control_ = control, + Event = eventMapping, + Attribute = controlAttribute + }; ; + + this.Core.AddTuple(tuple); } } } diff --git a/src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs b/src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs index 73a78a1f..8220ec25 100644 --- a/src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs +++ b/src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs @@ -53,18 +53,29 @@ namespace WixToolset.Core.ExtensibilityServices public void CreateComplexReference(IntermediateSection section, SourceLineNumber sourceLineNumbers, ComplexReferenceParentType parentType, string parentId, string parentLanguage, ComplexReferenceChildType childType, string childId, bool isPrimary) { - var wixComplexReferenceRow = (WixComplexReferenceTuple)this.CreateRow(section, sourceLineNumbers, TupleDefinitionType.WixComplexReference); - wixComplexReferenceRow.Parent = parentId; - wixComplexReferenceRow.ParentType = parentType; - wixComplexReferenceRow.ParentLanguage = parentLanguage; - wixComplexReferenceRow.Child = childId; - wixComplexReferenceRow.ChildType = childType; - wixComplexReferenceRow.IsPrimary = isPrimary; - this.CreateWixGroupRow(section, sourceLineNumbers, parentType, parentId, childType, childId); + var tuple = new WixComplexReferenceTuple(sourceLineNumbers) + { + Parent = parentId, + ParentType = parentType, + ParentLanguage = parentLanguage, + Child = childId, + ChildType = childType, + IsPrimary = isPrimary + }; + + section.Tuples.Add(tuple); + + this.CreateWixGroupTuple(section, sourceLineNumbers, parentType, parentId, childType, childId); } + [Obsolete] public Identifier CreateDirectoryRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, Identifier id, string parentId, string name, ISet sectionInlinedDirectoryIds, string shortName = null, string sourceName = null, string shortSourceName = null) + { + return this.CreateDirectoryTuple(section, sourceLineNumbers, id, parentId, name, sectionInlinedDirectoryIds, shortName, sourceName, shortSourceName); + } + + public Identifier CreateDirectoryTuple(IntermediateSection section, SourceLineNumber sourceLineNumbers, Identifier id, string parentId, string name, ISet sectionInlinedDirectoryIds, string shortName = null, string sourceName = null, string shortSourceName = null) { string defaultDir; @@ -158,7 +169,7 @@ namespace WixToolset.Core.ExtensibilityServices for (int i = pathStartsAt; i < inlineSyntax.Length; ++i) { - Identifier inlineId = this.CreateDirectoryRow(section, sourceLineNumbers, null, id, inlineSyntax[i], sectionInlinedDirectoryIds); + Identifier inlineId = this.CreateDirectoryTuple(section, sourceLineNumbers, null, id, inlineSyntax[i], sectionInlinedDirectoryIds); id = inlineId.Id; } } @@ -175,16 +186,22 @@ namespace WixToolset.Core.ExtensibilityServices public Identifier CreateIdentifier(string prefix, params string[] args) { var id = Common.GenerateIdentifier(prefix, args); - return new Identifier(id, AccessModifier.Private); + return new Identifier(AccessModifier.Private, id); } public Identifier CreateIdentifierFromFilename(string filename) { var id = Common.GetIdentifierFromName(filename); - return new Identifier(id, AccessModifier.Private); + return new Identifier(AccessModifier.Private, id); } + [Obsolete] public Identifier CreateRegistryRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, RegistryRootType root, string key, string name, string value, string componentId, bool escapeLeadingHash) + { + return this.CreateRegistryTuple(section, sourceLineNumbers, root, key, name, value, componentId, escapeLeadingHash); + } + + public Identifier CreateRegistryTuple(IntermediateSection section, SourceLineNumber sourceLineNumbers, RegistryRootType root, string key, string name, string value, string componentId, bool escapeLeadingHash) { if (RegistryRootType.Unknown == root) { @@ -234,7 +251,13 @@ namespace WixToolset.Core.ExtensibilityServices section.Tuples.Add(tuple); } + [Obsolete] public void CreateWixGroupRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, ComplexReferenceParentType parentType, string parentId, ComplexReferenceChildType childType, string childId) + { + this.CreateWixGroupTuple(section, sourceLineNumbers, parentType, parentId, childType, childId); + } + + public void CreateWixGroupTuple(IntermediateSection section, SourceLineNumber sourceLineNumbers, ComplexReferenceParentType parentType, string parentId, ComplexReferenceChildType childType, string childId) { if (null == parentId || ComplexReferenceParentType.Unknown == parentType) { @@ -257,7 +280,19 @@ namespace WixToolset.Core.ExtensibilityServices section.Tuples.Add(tuple); } + [Obsolete] public IntermediateTuple CreateRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, string tableName, Identifier identifier = null) + { + return this.CreateTuple(section, sourceLineNumbers, tableName, identifier); + } + + [Obsolete] + public IntermediateTuple CreateRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, TupleDefinitionType tupleType, Identifier identifier = null) + { + return this.CreateTuple(section, sourceLineNumbers, tupleType, identifier); + } + + public IntermediateTuple CreateTuple(IntermediateSection section, SourceLineNumber sourceLineNumbers, string tableName, Identifier identifier = null) { if (this.Creator == null) { @@ -272,7 +307,7 @@ namespace WixToolset.Core.ExtensibilityServices return CreateRow(section, sourceLineNumbers, tupleDefinition, identifier); } - public IntermediateTuple CreateRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, TupleDefinitionType tupleType, Identifier identifier = null) + public IntermediateTuple CreateTuple(IntermediateSection section, SourceLineNumber sourceLineNumbers, TupleDefinitionType tupleType, Identifier identifier = null) { var tupleDefinition = TupleDefinitions.ByType(tupleType); @@ -331,7 +366,7 @@ namespace WixToolset.Core.ExtensibilityServices public void EnsureTable(IntermediateSection section, SourceLineNumber sourceLineNumbers, string tableName) { - var row = this.CreateRow(section, sourceLineNumbers, TupleDefinitionType.WixEnsureTable); + var row = this.CreateTuple(section, sourceLineNumbers, TupleDefinitionType.WixEnsureTable); row.Set(0, tableName); if (this.Creator == null) @@ -428,7 +463,7 @@ namespace WixToolset.Core.ExtensibilityServices this.Messaging.Write(WarningMessages.IdentifierTooLong(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value)); } - return new Identifier(value, access); + return new Identifier(access, value); } public string GetAttributeIdentifierValue(SourceLineNumber sourceLineNumbers, XAttribute attribute) diff --git a/src/WixToolset.Core/Link/WixGroupingOrdering.cs b/src/WixToolset.Core/Link/WixGroupingOrdering.cs index 4e89e607..c40af502 100644 --- a/src/WixToolset.Core/Link/WixGroupingOrdering.cs +++ b/src/WixToolset.Core/Link/WixGroupingOrdering.cs @@ -18,11 +18,11 @@ namespace WixToolset.Core.Link /// internal class WixGroupingOrdering { - private IMessaging messageHandler; + private readonly IMessaging messageHandler; private List groupTypes; private List itemTypes; private ItemCollection items; - private List rowsUsed; + private readonly List rowsUsed; private bool loaded; private bool encounteredError; @@ -50,10 +50,10 @@ namespace WixToolset.Core.Link /// /// Group types to include. /// Item types to include. - public void UseTypes(IEnumerable groupTypes, IEnumerable itemTypes) + public void UseTypes(IEnumerable groupTypes, IEnumerable itemTypes) { - this.groupTypes = new List(groupTypes); - this.itemTypes = new List(itemTypes); + this.groupTypes = new List(groupTypes.Select(g => g.ToString())); + this.itemTypes = new List(itemTypes.Select(i => i.ToString())); this.items = new ItemCollection(); this.loaded = false; @@ -65,17 +65,18 @@ namespace WixToolset.Core.Link /// The group type for the parent group to flatten. /// The identifier of the parent group to flatten. /// Whether to remove used group rows before returning. - public void FlattenAndRewriteRows(string parentType, string parentId, bool removeUsedRows) + public void FlattenAndRewriteRows(ComplexReferenceChildType parentType, string parentId, bool removeUsedRows) { - Debug.Assert(this.groupTypes.Contains(parentType)); + var parentTypeString = parentType.ToString(); + Debug.Assert(this.groupTypes.Contains(parentTypeString)); - this.CreateOrderedList(parentType, parentId, out var orderedItems); + this.CreateOrderedList(parentTypeString, parentId, out var orderedItems); if (this.encounteredError) { return; } - this.CreateNewGroupRows(parentType, parentId, orderedItems); + this.CreateNewGroupRows(parentTypeString, parentId, orderedItems); if (removeUsedRows) { @@ -88,9 +89,10 @@ namespace WixToolset.Core.Link /// /// The type of the parent group to flatten. /// Whether to remove used group rows before returning. - public void FlattenAndRewriteGroups(string parentType, bool removeUsedRows) + public void FlattenAndRewriteGroups(ComplexReferenceParentType parentType, bool removeUsedRows) { - Debug.Assert(this.groupTypes.Contains(parentType)); + var parentTypeString = parentType.ToString(); + Debug.Assert(this.groupTypes.Contains(parentTypeString)); this.LoadFlattenOrderGroups(); if (this.encounteredError) @@ -100,10 +102,9 @@ namespace WixToolset.Core.Link foreach (Item item in this.items) { - if (parentType == item.Type) + if (parentTypeString == item.Type) { - List orderedItems; - this.CreateOrderedList(item.Type, item.Id, out orderedItems); + this.CreateOrderedList(item.Type, item.Id, out var orderedItems); this.CreateNewGroupRows(item.Type, item.Id, orderedItems); } } @@ -131,8 +132,7 @@ namespace WixToolset.Core.Link return; } - Item parentItem; - if (!this.items.TryGetValue(parentType, parentId, out parentItem)) + if (!this.items.TryGetValue(parentType, parentId, out var parentItem)) { this.messageHandler.Write(ErrorMessages.IdentifierNotFound(parentType, parentId)); return; @@ -360,9 +360,9 @@ namespace WixToolset.Core.Link foreach (var row in this.EntrySection.Tuples.OfType()) { - var rowItemType = row.ItemType; + var rowItemType = row.ItemType.ToString(); var rowItemName = row.ItemId_; - var rowDependsOnType = row.DependsOnType; + var rowDependsOnType = row.DependsOnType.ToString(); var rowDependsOnName = row.DependsOnId_; // If this row specifies some other (unknown) type in either @@ -510,8 +510,8 @@ namespace WixToolset.Core.Link /// ordering dependencies. internal class Item { - private ItemCollection afterItems; - private ItemCollection beforeItems; // for checking for circular references + private readonly ItemCollection afterItems; + private readonly ItemCollection beforeItems; // for checking for circular references private bool flattenedAfterItems; public Item(IntermediateTuple row, string type, string id) @@ -522,9 +522,9 @@ namespace WixToolset.Core.Link this.Key = ItemCollection.CreateKeyFromTypeId(type, id); - afterItems = new ItemCollection(); - beforeItems = new ItemCollection(); - flattenedAfterItems = false; + this.afterItems = new ItemCollection(); + this.beforeItems = new ItemCollection(); + this.flattenedAfterItems = false; } public IntermediateTuple Row { get; private set; } @@ -540,8 +540,7 @@ namespace WixToolset.Core.Link } #endif // DEBUG - private ItemCollection childItems = new ItemCollection(); - public ItemCollection ChildItems { get { return childItems; } } + public ItemCollection ChildItems { get; } = new ItemCollection(); /// /// Removes any nested groups under this item and replaces @@ -614,7 +613,7 @@ namespace WixToolset.Core.Link { if (this.ShouldItemPropagateChildOrdering()) { - foreach (Item childItem in this.childItems) + foreach (Item childItem in this.ChildItems) { childItem.AddAfter(this.afterItems, messageHandler); } @@ -667,9 +666,9 @@ namespace WixToolset.Core.Link // first payload to be the entrypoint. private bool ShouldItemPropagateChildOrdering() { - if (String.Equals("Package", this.Type, StringComparison.Ordinal) || - (String.Equals("Container", this.Type, StringComparison.Ordinal) && - !String.Equals(Compiler.BurnUXContainerId, this.Id, StringComparison.Ordinal))) + if (String.Equals(nameof(ComplexReferenceChildType.Package), this.Type, StringComparison.Ordinal) || + (String.Equals(nameof(ComplexReferenceParentType.Container), this.Type, StringComparison.Ordinal) && + !String.Equals(Compiler.BurnUXContainerId.Id, this.Id, StringComparison.Ordinal))) { return false; } diff --git a/src/WixToolset.Core/Linker.cs b/src/WixToolset.Core/Linker.cs index 13efe6c5..fa4c97b0 100644 --- a/src/WixToolset.Core/Linker.cs +++ b/src/WixToolset.Core/Linker.cs @@ -20,8 +20,8 @@ namespace WixToolset.Core /// internal class Linker : ILinker { - private static readonly char[] colonCharacter = ":".ToCharArray(); - private static readonly string emptyGuid = Guid.Empty.ToString("B"); + private static readonly char[] ColonCharacter = new[] { ':' }; + private static readonly string EmptyGuid = Guid.Empty.ToString("B"); private readonly bool sectionIdOnRows; @@ -428,21 +428,22 @@ namespace WixToolset.Core // check for colliding values and collect the wix variable rows { var row = (WixVariableTuple)tuple; + var id = row.Id.Id; - if (wixVariables.TryGetValue(row.WixVariable, out var collidingRow)) + if (wixVariables.TryGetValue(id, out var collidingRow)) { if (collidingRow.Overridable && !row.Overridable) { - wixVariables[row.WixVariable] = row; + wixVariables[id] = row; } else if (!row.Overridable || (collidingRow.Overridable && row.Overridable)) { - this.OnMessage(ErrorMessages.WixVariableCollision(row.SourceLineNumbers, row.WixVariable)); + this.OnMessage(ErrorMessages.WixVariableCollision(row.SourceLineNumbers, id)); } } else { - wixVariables.Add(row.WixVariable, row); + wixVariables.Add(id, row); } } @@ -1609,14 +1610,14 @@ namespace WixToolset.Core var groups = new WixGroupingOrdering(entrySection, this.Messaging); // Create UX payloads and Package payloads - groups.UseTypes(new string[] { "Container", "Layout", "PackageGroup", "PayloadGroup", "Package" }, new string[] { "PackageGroup", "Package", "PayloadGroup", "Payload" }); - groups.FlattenAndRewriteGroups("Package", false); - groups.FlattenAndRewriteGroups("Container", false); - groups.FlattenAndRewriteGroups("Layout", false); - + groups.UseTypes(new[] { ComplexReferenceParentType.Container, ComplexReferenceParentType.Layout, ComplexReferenceParentType.PackageGroup, ComplexReferenceParentType.PayloadGroup, ComplexReferenceParentType.Package }, new[] { ComplexReferenceChildType.PackageGroup, ComplexReferenceChildType.Package, ComplexReferenceChildType.PayloadGroup, ComplexReferenceChildType.Payload }); + groups.FlattenAndRewriteGroups(ComplexReferenceParentType.Package, false); + groups.FlattenAndRewriteGroups(ComplexReferenceParentType.Container, false); + groups.FlattenAndRewriteGroups(ComplexReferenceParentType.Layout, false); + // Create Chain packages... - groups.UseTypes(new string[] { "PackageGroup" }, new string[] { "Package", "PackageGroup" }); - groups.FlattenAndRewriteRows("PackageGroup", "WixChain", false); + groups.UseTypes(new[] { ComplexReferenceParentType.PackageGroup }, new[] { ComplexReferenceChildType.Package, ComplexReferenceChildType.PackageGroup }); + groups.FlattenAndRewriteRows(ComplexReferenceChildType.PackageGroup, "WixChain", false); groups.RemoveUsedGroupRows(); } @@ -1702,7 +1703,7 @@ namespace WixToolset.Core var connectionId = row.AsString(connectionColumn); var featureId = row.AsString(featureColumn); - if (emptyGuid == featureId) + if (EmptyGuid == featureId) { var connection = connectToFeatures[connectionId]; diff --git a/src/WixToolset.Core/Preprocessor.cs b/src/WixToolset.Core/Preprocessor.cs index d086cbd9..d897446c 100644 --- a/src/WixToolset.Core/Preprocessor.cs +++ b/src/WixToolset.Core/Preprocessor.cs @@ -66,7 +66,8 @@ namespace WixToolset.Core /// /// Event for resolved variables. /// - public event ResolvedVariableEventHandler ResolvedVariable; + /// TOOD: Remove? + //public event ResolvedVariableEventHandler ResolvedVariable; /// /// Get the source line information for the current element. The precompiler will insert diff --git a/src/WixToolset.Core/Resolver.cs b/src/WixToolset.Core/Resolver.cs index 4bdc5815..42c7c9fb 100644 --- a/src/WixToolset.Core/Resolver.cs +++ b/src/WixToolset.Core/Resolver.cs @@ -213,7 +213,7 @@ namespace WixToolset.Core var wixVariableTuples = context.IntermediateRepresentation.Sections.SelectMany(s => s.Tuples).OfType(); foreach (var tuple in wixVariableTuples) { - context.VariableResolver.AddVariable(tuple.SourceLineNumbers, tuple.WixVariable, tuple.Value, tuple.Overridable); + context.VariableResolver.AddVariable(tuple.SourceLineNumbers, tuple.Id.Id, tuple.Value, tuple.Overridable); } } diff --git a/src/WixToolset.Core/TransformsFlags.cs b/src/WixToolset.Core/TransformsFlags.cs deleted file mode 100644 index d9ec94ac..00000000 --- a/src/WixToolset.Core/TransformsFlags.cs +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. - -namespace WixToolset.Core -{ - using System; - using System.Diagnostics.CodeAnalysis; - - /// - /// Summary information values for the CharCount property in transforms. - /// - [Flags] - [SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")] - public enum TransformFlags - { - /// Ignore error when adding a row that exists. - ErrorAddExistingRow = 0x1, - - /// Ignore error when deleting a row that does not exist. - ErrorDeleteMissingRow = 0x2, - - /// Ignore error when adding a table that exists. - ErrorAddExistingTable = 0x4, - - /// Ignore error when deleting a table that does not exist. - ErrorDeleteMissingTable = 0x8, - - /// Ignore error when updating a row that does not exist. - ErrorUpdateMissingRow = 0x10, - - /// Ignore error when transform and database code pages do not match, and their code pages are neutral. - ErrorChangeCodePage = 0x20, - - /// Default language must match base database. - ValidateLanguage = 0x10000, - - /// Product must match base database. - ValidateProduct = 0x20000, - - /// Check major version only. - ValidateMajorVersion = 0x80000, - - /// Check major and minor versions only. - ValidateMinorVersion = 0x100000, - - /// Check major, minor, and update versions. - ValidateUpdateVersion = 0x200000, - - /// Installed version lt base version. - ValidateNewLessBaseVersion = 0x400000, - - /// Installed version lte base version. - ValidateNewLessEqualBaseVersion = 0x800000, - - /// Installed version eq base version. - ValidateNewEqualBaseVersion = 0x1000000, - - /// Installed version gte base version. - ValidateNewGreaterEqualBaseVersion = 0x2000000, - - /// Installed version gt base version. - ValidateNewGreaterBaseVersion = 0x4000000, - - /// UpgradeCode must match base database. - ValidateUpgradeCode = 0x8000000, - - /// Masks all version checks on ProductVersion. - ProductVersionMask = ValidateMajorVersion | ValidateMinorVersion | ValidateUpdateVersion, - - /// Masks all operations on ProductVersion. - ProductVersionOperatorMask = ValidateNewLessBaseVersion | ValidateNewLessEqualBaseVersion | ValidateNewEqualBaseVersion | ValidateNewGreaterEqualBaseVersion | ValidateNewGreaterBaseVersion, - - /// Default value for instance transforms. - InstanceTransformDefault = ErrorAddExistingRow | ErrorDeleteMissingRow | ErrorAddExistingTable | ErrorDeleteMissingTable | ErrorUpdateMissingRow | ErrorChangeCodePage | ValidateProduct | ValidateUpdateVersion | ValidateNewGreaterEqualBaseVersion, - - /// Default value for language transforms. - LanguageTransformDefault = ErrorAddExistingRow | ErrorDeleteMissingRow | ErrorAddExistingTable | ErrorDeleteMissingTable | ErrorUpdateMissingRow | ErrorChangeCodePage | ValidateProduct, - - /// Default value for patch transforms. - PatchTransformDefault = ErrorAddExistingRow | ErrorDeleteMissingRow | ErrorAddExistingTable | ErrorDeleteMissingTable | ErrorUpdateMissingRow | ValidateProduct | ValidateUpdateVersion | ValidateNewEqualBaseVersion | ValidateUpgradeCode, - } -} -- cgit v1.2.3-55-g6feb