aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2019-05-22 00:58:13 -0700
committerRob Mensching <rob@firegiant.com>2019-05-23 16:02:37 -0700
commitd0462be8000f18aa7dc0791d02142f000bb19fbf (patch)
tree072aabc2bd9b8f171e17654473f85c44a8a42a66 /src/WixToolset.Core
parent1ed894bc0f39397ec7f7f6344370fc2123420c43 (diff)
downloadwix-d0462be8000f18aa7dc0791d02142f000bb19fbf.tar.gz
wix-d0462be8000f18aa7dc0791d02142f000bb19fbf.tar.bz2
wix-d0462be8000f18aa7dc0791d02142f000bb19fbf.zip
Integrate latest changes to tuple definitions
Diffstat (limited to 'src/WixToolset.Core')
-rw-r--r--src/WixToolset.Core/Compiler.cs2577
-rw-r--r--src/WixToolset.Core/CompilerCore.cs150
-rw-r--r--src/WixToolset.Core/Compiler_2.cs1465
-rw-r--r--src/WixToolset.Core/Compiler_Bundle.cs467
-rw-r--r--src/WixToolset.Core/Compiler_EmbeddedUI.cs12
-rw-r--r--src/WixToolset.Core/Compiler_Module.cs79
-rw-r--r--src/WixToolset.Core/Compiler_Patch.cs655
-rw-r--r--src/WixToolset.Core/Compiler_PatchCreation.cs1313
-rw-r--r--src/WixToolset.Core/Compiler_UI.cs117
-rw-r--r--src/WixToolset.Core/ExtensibilityServices/ParseHelper.cs63
-rw-r--r--src/WixToolset.Core/Link/WixGroupingOrdering.cs57
-rw-r--r--src/WixToolset.Core/Linker.cs29
-rw-r--r--src/WixToolset.Core/Preprocessor.cs3
-rw-r--r--src/WixToolset.Core/Resolver.cs2
-rw-r--r--src/WixToolset.Core/TransformsFlags.cs81
15 files changed, 3567 insertions, 3503 deletions
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
21 /// </summary> 21 /// </summary>
22 internal partial class Compiler : ICompiler 22 internal partial class Compiler : ICompiler
23 { 23 {
24 public const string DefaultComponentIdPlaceholderFormat = "WixComponentIdPlaceholder{0}"; 24 private const int MinValueOfMaxCabSizeForLargeFileSplitting = 20; // 20 MB
25 public const string DefaultComponentIdPlaceholderWixVariableFormat = "!(wix.{0})"; 25 private const int MaxValueOfMaxCabSizeForLargeFileSplitting = 2 * 1024; // 2048 MB (i.e. 2 GB)
26
27 private const string DefaultComponentIdPlaceholderFormat = "WixComponentIdPlaceholder{0}";
28 private const string DefaultComponentIdPlaceholderWixVariableFormat = "!(wix.{0})";
26 // If these are true you know you are building a module or product 29 // If these are true you know you are building a module or product
27 // but if they are false you cannot not be sure they will not end 30 // but if they are false you cannot not be sure they will not end
28 // up a product or module. Use these flags carefully. 31 // up a product or module. Use these flags carefully.
@@ -164,6 +167,76 @@ namespace WixToolset.Core
164 return this.Messaging.EncounteredError ? null : target; 167 return this.Messaging.EncounteredError ? null : target;
165 } 168 }
166 169
170 /// <summary>
171 /// Parses a Wix element.
172 /// </summary>
173 /// <param name="node">Element to parse.</param>
174 private void ParseWixElement(XElement node)
175 {
176 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
177 string requiredVersion = null;
178
179 foreach (var attrib in node.Attributes())
180 {
181 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
182 {
183 switch (attrib.Name.LocalName)
184 {
185 case "RequiredVersion":
186 requiredVersion = this.Core.GetAttributeVersionValue(sourceLineNumbers, attrib);
187 break;
188 default:
189 this.Core.UnexpectedAttribute(node, attrib);
190 break;
191 }
192 }
193 else
194 {
195 this.Core.ParseExtensionAttribute(node, attrib);
196 }
197 }
198
199 if (null != requiredVersion)
200 {
201 this.Core.VerifyRequiredVersion(sourceLineNumbers, requiredVersion);
202 }
203
204 foreach (var child in node.Elements())
205 {
206 if (CompilerCore.WixNamespace == child.Name.Namespace)
207 {
208 switch (child.Name.LocalName)
209 {
210 case "Bundle":
211 this.ParseBundleElement(child);
212 break;
213 case "Fragment":
214 this.ParseFragmentElement(child);
215 break;
216 case "Module":
217 this.ParseModuleElement(child);
218 break;
219 case "PatchCreation":
220 this.ParsePatchCreationElement(child);
221 break;
222 case "Product":
223 this.ParseProductElement(child);
224 break;
225 case "Patch":
226 this.ParsePatchElement(child);
227 break;
228 default:
229 this.Core.UnexpectedElement(node, child);
230 break;
231 }
232 }
233 else
234 {
235 this.Core.ParseExtensionElement(node, child);
236 }
237 }
238 }
239
167 private void ResolveComponentIdPlaceholders(Intermediate target) 240 private void ResolveComponentIdPlaceholders(Intermediate target)
168 { 241 {
169 if (0 < this.componentIdPlaceholdersResolver.VariableCount) 242 if (0 < this.componentIdPlaceholdersResolver.VariableCount)
@@ -214,7 +287,7 @@ namespace WixToolset.Core
214 /// <returns>Null if the string is null, otherwise returns the lowercase.</returns> 287 /// <returns>Null if the string is null, otherwise returns the lowercase.</returns>
215 private static string LowercaseOrNull(string s) 288 private static string LowercaseOrNull(string s)
216 { 289 {
217 return (null == s) ? s : s.ToLowerInvariant(); 290 return s?.ToLowerInvariant();
218 } 291 }
219 292
220 /// <summary> 293 /// <summary>
@@ -227,18 +300,11 @@ namespace WixToolset.Core
227 { 300 {
228 if (null != shortName && null != longName && !String.Equals(shortName, longName, StringComparison.OrdinalIgnoreCase)) 301 if (null != shortName && null != longName && !String.Equals(shortName, longName, StringComparison.OrdinalIgnoreCase))
229 { 302 {
230 return String.Format(CultureInfo.InvariantCulture, "{0}|{1}", shortName, longName); 303 return String.Concat(shortName, "|", longName);
231 } 304 }
232 else 305 else
233 { 306 {
234 if (this.Core.IsValidShortFilename(longName, false)) 307 return this.Core.IsValidShortFilename(longName, false) ? longName : shortName;
235 {
236 return longName;
237 }
238 else
239 {
240 return shortName;
241 }
242 } 308 }
243 } 309 }
244 310
@@ -246,19 +312,23 @@ namespace WixToolset.Core
246 /// Adds a search property to the active section. 312 /// Adds a search property to the active section.
247 /// </summary> 313 /// </summary>
248 /// <param name="sourceLineNumbers">Current source/line number of processing.</param> 314 /// <param name="sourceLineNumbers">Current source/line number of processing.</param>
249 /// <param name="property">Property to add to search.</param> 315 /// <param name="propertyId">Property to add to search.</param>
250 /// <param name="signature">Signature for search.</param> 316 /// <param name="signature">Signature for search.</param>
251 private void AddAppSearch(SourceLineNumber sourceLineNumbers, Identifier property, string signature) 317 private void AddAppSearch(SourceLineNumber sourceLineNumbers, Identifier propertyId, string signature)
252 { 318 {
253 if (!this.Core.EncounteredError) 319 if (!this.Core.EncounteredError)
254 { 320 {
255 if (property.Id != property.Id.ToUpperInvariant()) 321 if (propertyId.Id != propertyId.Id.ToUpperInvariant())
256 { 322 {
257 this.Core.Write(ErrorMessages.SearchPropertyNotUppercase(sourceLineNumbers, "Property", "Id", property.Id)); 323 this.Core.Write(ErrorMessages.SearchPropertyNotUppercase(sourceLineNumbers, "Property", "Id", propertyId.Id));
258 } 324 }
259 325
260 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.AppSearch, property); 326 var tuple = new AppSearchTuple(sourceLineNumbers, propertyId)
261 row.Set(1, signature); 327 {
328 Signature_ = signature
329 };
330
331 this.Core.AddTuple(tuple);
262 } 332 }
263 } 333 }
264 334
@@ -266,16 +336,16 @@ namespace WixToolset.Core
266 /// Adds a property to the active section. 336 /// Adds a property to the active section.
267 /// </summary> 337 /// </summary>
268 /// <param name="sourceLineNumbers">Current source/line number of processing.</param> 338 /// <param name="sourceLineNumbers">Current source/line number of processing.</param>
269 /// <param name="property">Name of property to add.</param> 339 /// <param name="propertyId">Identifier of property to add.</param>
270 /// <param name="value">Value of property.</param> 340 /// <param name="value">Value of property.</param>
271 /// <param name="admin">Flag if property is an admin property.</param> 341 /// <param name="admin">Flag if property is an admin property.</param>
272 /// <param name="secure">Flag if property is a secure property.</param> 342 /// <param name="secure">Flag if property is a secure property.</param>
273 /// <param name="hidden">Flag if property is to be hidden.</param> 343 /// <param name="hidden">Flag if property is to be hidden.</param>
274 /// <param name="fragment">Adds the property to a new section.</param> 344 /// <param name="fragment">Adds the property to a new section.</param>
275 private void AddProperty(SourceLineNumber sourceLineNumbers, Identifier property, string value, bool admin, bool secure, bool hidden, bool fragment) 345 private void AddProperty(SourceLineNumber sourceLineNumbers, Identifier propertyId, string value, bool admin, bool secure, bool hidden, bool fragment)
276 { 346 {
277 // properties without a valid identifier should not be processed any further 347 // properties without a valid identifier should not be processed any further
278 if (null == property || String.IsNullOrEmpty(property.Id)) 348 if (null == propertyId || String.IsNullOrEmpty(propertyId.Id))
279 { 349 {
280 return; 350 return;
281 } 351 }
@@ -290,7 +360,7 @@ namespace WixToolset.Core
290 var group = match.Groups["identifier"]; 360 var group = match.Groups["identifier"];
291 if (group.Success) 361 if (group.Success)
292 { 362 {
293 this.Core.Write(WarningMessages.PropertyValueContainsPropertyReference(sourceLineNumbers, property.Id, group.Value)); 363 this.Core.Write(WarningMessages.PropertyValueContainsPropertyReference(sourceLineNumbers, propertyId.Id, group.Value));
294 } 364 }
295 } 365 }
296 } 366 }
@@ -302,26 +372,26 @@ namespace WixToolset.Core
302 // Add the row to a separate section if requested. 372 // Add the row to a separate section if requested.
303 if (fragment) 373 if (fragment)
304 { 374 {
305 var id = String.Concat(this.Core.ActiveSection.Id, ".", property.Id); 375 var id = String.Concat(this.Core.ActiveSection.Id, ".", propertyId.Id);
306 376
307 section = this.Core.CreateSection(id, SectionType.Fragment, this.Core.ActiveSection.Codepage, this.Context.CompilationId); 377 section = this.Core.CreateSection(id, SectionType.Fragment, this.Core.ActiveSection.Codepage, this.Context.CompilationId);
308 378
309 // Reference the property in the active section. 379 // Reference the property in the active section.
310 this.Core.CreateSimpleReference(sourceLineNumbers, "Property", property.Id); 380 this.Core.CreateSimpleReference(sourceLineNumbers, "Property", propertyId.Id);
311 } 381 }
312 382
313 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Property, section, property);
314
315 // Allow row to exist with no value so that PropertyRefs can be made for *Search elements 383 // Allow row to exist with no value so that PropertyRefs can be made for *Search elements
316 // the linker will remove these rows before the final output is created. 384 // the linker will remove these rows before the final output is created.
317 if (null != value) 385 var tuple = new PropertyTuple(sourceLineNumbers, propertyId)
318 { 386 {
319 row.Set(1, value); 387 Value = value,
320 } 388 };
389
390 section.Tuples.Add(tuple);
321 391
322 if (admin || hidden || secure) 392 if (admin || hidden || secure)
323 { 393 {
324 this.AddWixPropertyRow(sourceLineNumbers, property, admin, secure, hidden, section); 394 this.AddWixPropertyRow(sourceLineNumbers, propertyId, admin, secure, hidden, section);
325 } 395 }
326 } 396 }
327 } 397 }
@@ -340,10 +410,15 @@ namespace WixToolset.Core
340 this.Core.EnsureTable(sourceLineNumbers, "Property"); // Property table is always required when using WixProperty table. 410 this.Core.EnsureTable(sourceLineNumbers, "Property"); // Property table is always required when using WixProperty table.
341 } 411 }
342 412
343 var row = (WixPropertyTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixProperty, section, property); 413 var tuple = new WixPropertyTuple(sourceLineNumbers)
344 row.Admin = admin; 414 {
345 row.Hidden = hidden; 415 Property_ = property.Id,
346 row.Secure = secure; 416 Admin = admin,
417 Hidden = hidden,
418 Secure = secure
419 };
420
421 section.Tuples.Add(tuple);
347 } 422 }
348 423
349 /// <summary> 424 /// <summary>
@@ -375,9 +450,9 @@ namespace WixToolset.Core
375 string localService = null; 450 string localService = null;
376 string serviceParameters = null; 451 string serviceParameters = null;
377 string dllSurrogate = null; 452 string dllSurrogate = null;
378 var activateAtStorage = YesNoType.NotSet; 453 bool? activateAtStorage = null;
379 var appIdAdvertise = YesNoType.NotSet; 454 var appIdAdvertise = YesNoType.NotSet;
380 var runAsInteractiveUser = YesNoType.NotSet; 455 bool? runAsInteractiveUser = null;
381 string description = null; 456 string description = null;
382 457
383 foreach (var attrib in node.Attributes()) 458 foreach (var attrib in node.Attributes())
@@ -390,7 +465,7 @@ namespace WixToolset.Core
390 appId = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false); 465 appId = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false);
391 break; 466 break;
392 case "ActivateAtStorage": 467 case "ActivateAtStorage":
393 activateAtStorage = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); 468 activateAtStorage = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
394 break; 469 break;
395 case "Advertise": 470 case "Advertise":
396 appIdAdvertise = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); 471 appIdAdvertise = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
@@ -408,7 +483,7 @@ namespace WixToolset.Core
408 remoteServerName = this.Core.GetAttributeValue(sourceLineNumbers, attrib); 483 remoteServerName = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
409 break; 484 break;
410 case "RunAsInteractiveUser": 485 case "RunAsInteractiveUser":
411 runAsInteractiveUser = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); 486 runAsInteractiveUser = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
412 break; 487 break;
413 case "ServiceParameters": 488 case "ServiceParameters":
414 serviceParameters = this.Core.GetAttributeValue(sourceLineNumbers, attrib); 489 serviceParameters = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
@@ -473,21 +548,19 @@ namespace WixToolset.Core
473 548
474 if (!this.Core.EncounteredError) 549 if (!this.Core.EncounteredError)
475 { 550 {
476 var id = new Identifier(appId, AccessModifier.Public); 551 var id = new Identifier(AccessModifier.Public, appId);
477 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.AppId, id);
478 row.Set(1, remoteServerName);
479 row.Set(2, localService);
480 row.Set(3, serviceParameters);
481 row.Set(4, dllSurrogate);
482 if (YesNoType.Yes == activateAtStorage)
483 {
484 row.Set(5, 1);
485 }
486 552
487 if (YesNoType.Yes == runAsInteractiveUser) 553 var tuple = new AppIdTuple(sourceLineNumbers, id)
488 { 554 {
489 row.Set(6, 1); 555 RemoteServerName = remoteServerName,
490 } 556 LocalService = localService,
557 ServiceParameters = serviceParameters,
558 DllSurrogate = dllSurrogate,
559 ActivateAtStorage = activateAtStorage,
560 RunAsInteractiveUser = runAsInteractiveUser
561 };
562
563 this.Core.AddTuple(tuple);
491 } 564 }
492 } 565 }
493 else if (YesNoType.No == advertise) 566 else if (YesNoType.No == advertise)
@@ -521,12 +594,12 @@ namespace WixToolset.Core
521 this.Core.CreateRegistryRow(sourceLineNumbers, RegistryRootType.ClassesRoot, String.Concat("AppID\\", appId), "DllSurrogate", dllSurrogate, componentId); 594 this.Core.CreateRegistryRow(sourceLineNumbers, RegistryRootType.ClassesRoot, String.Concat("AppID\\", appId), "DllSurrogate", dllSurrogate, componentId);
522 } 595 }
523 596
524 if (YesNoType.Yes == activateAtStorage) 597 if (true == activateAtStorage)
525 { 598 {
526 this.Core.CreateRegistryRow(sourceLineNumbers, RegistryRootType.ClassesRoot, String.Concat("AppID\\", appId), "ActivateAtStorage", "Y", componentId); 599 this.Core.CreateRegistryRow(sourceLineNumbers, RegistryRootType.ClassesRoot, String.Concat("AppID\\", appId), "ActivateAtStorage", "Y", componentId);
527 } 600 }
528 601
529 if (YesNoType.Yes == runAsInteractiveUser) 602 if (true == runAsInteractiveUser)
530 { 603 {
531 this.Core.CreateRegistryRow(sourceLineNumbers, RegistryRootType.ClassesRoot, String.Concat("AppID\\", appId), "RunAs", "Interactive User", componentId); 604 this.Core.CreateRegistryRow(sourceLineNumbers, RegistryRootType.ClassesRoot, String.Concat("AppID\\", appId), "RunAs", "Interactive User", componentId);
532 } 605 }
@@ -576,10 +649,14 @@ namespace WixToolset.Core
576 649
577 if (!this.Core.EncounteredError) 650 if (!this.Core.EncounteredError)
578 { 651 {
579 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiAssemblyName); 652 var tuple = new MsiAssemblyNameTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, componentId, id))
580 row.Set(0, componentId); 653 {
581 row.Set(1, id); 654 Component_ = componentId,
582 row.Set(2, value); 655 Name = id,
656 Value = value
657 };
658
659 this.Core.AddTuple(tuple);
583 } 660 }
584 } 661 }
585 662
@@ -661,12 +738,16 @@ namespace WixToolset.Core
661 738
662 if (!this.Core.EncounteredError) 739 if (!this.Core.EncounteredError)
663 { 740 {
664 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Binary, id); 741 var tuple = new BinaryTuple(sourceLineNumbers, id)
665 row.Set(1, sourceFile); 742 {
743 Data = sourceFile
744 };
745
746 this.Core.AddTuple(tuple);
666 747
667 if (YesNoType.Yes == suppressModularization) 748 if (YesNoType.Yes == suppressModularization)
668 { 749 {
669 var wixSuppressModularizationRow = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixSuppressModularization, id); 750 this.Core.AddTuple(new WixSuppressModularizationTuple(sourceLineNumbers, id));
670 } 751 }
671 } 752 }
672 753
@@ -736,8 +817,10 @@ namespace WixToolset.Core
736 817
737 if (!this.Core.EncounteredError) 818 if (!this.Core.EncounteredError)
738 { 819 {
739 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Icon, id); 820 this.Core.AddTuple(new IconTuple(sourceLineNumbers, id)
740 row.Set(1, sourceFile); 821 {
822 Data = sourceFile
823 });
741 } 824 }
742 825
743 return id.Id; 826 return id.Id;
@@ -808,7 +891,7 @@ namespace WixToolset.Core
808 private void ParseInstanceElement(XElement node, string propertyId) 891 private void ParseInstanceElement(XElement node, string propertyId)
809 { 892 {
810 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); 893 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
811 string id = null; 894 Identifier id = null;
812 string productCode = null; 895 string productCode = null;
813 string productName = null; 896 string productName = null;
814 string upgradeCode = null; 897 string upgradeCode = null;
@@ -820,7 +903,7 @@ namespace WixToolset.Core
820 switch (attrib.Name.LocalName) 903 switch (attrib.Name.LocalName)
821 { 904 {
822 case "Id": 905 case "Id":
823 id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); 906 id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib);
824 break; 907 break;
825 case "ProductCode": 908 case "ProductCode":
826 productCode = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, true); 909 productCode = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, true);
@@ -856,18 +939,15 @@ namespace WixToolset.Core
856 939
857 if (!this.Core.EncounteredError) 940 if (!this.Core.EncounteredError)
858 { 941 {
859 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixInstanceTransforms); 942 var tuple = new WixInstanceTransformsTuple(sourceLineNumbers, id)
860 row.Set(0, id);
861 row.Set(1, propertyId);
862 row.Set(2, productCode);
863 if (null != productName)
864 {
865 row.Set(3, productName);
866 }
867 if (null != upgradeCode)
868 { 943 {
869 row.Set(4, upgradeCode); 944 PropertyId = propertyId,
870 } 945 ProductCode = productCode,
946 ProductName = productName,
947 UpgradeCode = upgradeCode
948 };
949
950 this.Core.AddTuple(tuple);
871 } 951 }
872 } 952 }
873 953
@@ -928,19 +1008,16 @@ namespace WixToolset.Core
928 1008
929 if (!this.Core.EncounteredError) 1009 if (!this.Core.EncounteredError)
930 { 1010 {
931 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PublishComponent); 1011 var tuple = new PublishComponentTuple(sourceLineNumbers)
932 row.Set(0, id);
933 row.Set(1, qualifier);
934 row.Set(2, componentId);
935 row.Set(3, appData);
936 if (null == feature)
937 { 1012 {
938 row.Set(4, Guid.Empty.ToString("B")); 1013 ComponentId = id,
939 } 1014 Qualifier = qualifier,
940 else 1015 Component_ = componentId,
941 { 1016 AppData = appData,
942 row.Set(4, feature); 1017 Feature_ = feature ?? Guid.Empty.ToString("B"),
943 } 1018 };
1019
1020 this.Core.AddTuple(tuple);
944 } 1021 }
945 } 1022 }
946 1023
@@ -1662,7 +1739,7 @@ namespace WixToolset.Core
1662 string name = null; 1739 string name = null;
1663 string signature = null; 1740 string signature = null;
1664 RegistryRootType? root = null; 1741 RegistryRootType? root = null;
1665 var type = CompilerConstants.IntegerNotSet; 1742 RegLocatorType? type = null;
1666 var search64bit = false; 1743 var search64bit = false;
1667 1744
1668 foreach (var attrib in node.Attributes()) 1745 foreach (var attrib in node.Attributes())
@@ -1688,13 +1765,13 @@ namespace WixToolset.Core
1688 switch (typeValue) 1765 switch (typeValue)
1689 { 1766 {
1690 case "directory": 1767 case "directory":
1691 type = 0; 1768 type = RegLocatorType.Directory;
1692 break; 1769 break;
1693 case "file": 1770 case "file":
1694 type = 1; 1771 type = RegLocatorType.FileName;
1695 break; 1772 break;
1696 case "raw": 1773 case "raw":
1697 type = 2; 1774 type = RegLocatorType.Raw;
1698 break; 1775 break;
1699 case "": 1776 case "":
1700 break; 1777 break;
@@ -1738,7 +1815,7 @@ namespace WixToolset.Core
1738 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Root")); 1815 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Root"));
1739 } 1816 }
1740 1817
1741 if (CompilerConstants.IntegerNotSet == type) 1818 if (!type.HasValue)
1742 { 1819 {
1743 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Type")); 1820 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Type"));
1744 } 1821 }
@@ -1776,7 +1853,7 @@ namespace WixToolset.Core
1776 } 1853 }
1777 oneChild = true; 1854 oneChild = true;
1778 signature = this.ParseFileSearchElement(child, id.Id, false, CompilerConstants.IntegerNotSet); 1855 signature = this.ParseFileSearchElement(child, id.Id, false, CompilerConstants.IntegerNotSet);
1779 id = new Identifier(signature, AccessModifier.Private); // FileSearch signatures override parent signatures 1856 id = new Identifier(AccessModifier.Private, signature); // FileSearch signatures override parent signatures
1780 break; 1857 break;
1781 case "FileSearchRef": 1858 case "FileSearchRef":
1782 if (oneChild) 1859 if (oneChild)
@@ -1785,7 +1862,7 @@ namespace WixToolset.Core
1785 } 1862 }
1786 oneChild = true; 1863 oneChild = true;
1787 var newId = this.ParseSimpleRefElement(child, "Signature"); // FileSearch signatures override parent signatures 1864 var newId = this.ParseSimpleRefElement(child, "Signature"); // FileSearch signatures override parent signatures
1788 id = new Identifier(newId, AccessModifier.Private); 1865 id = new Identifier(AccessModifier.Private, newId);
1789 signature = null; 1866 signature = null;
1790 break; 1867 break;
1791 default: 1868 default:
@@ -1799,14 +1876,18 @@ namespace WixToolset.Core
1799 } 1876 }
1800 } 1877 }
1801 1878
1802
1803 if (!this.Core.EncounteredError) 1879 if (!this.Core.EncounteredError)
1804 { 1880 {
1805 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.RegLocator, id); 1881 var tuple = new RegLocatorTuple(sourceLineNumbers, id)
1806 row.Set(1, (int)root); 1882 {
1807 row.Set(2, key); 1883 Root = root.Value,
1808 row.Set(3, name); 1884 Key = key,
1809 row.Set(4, search64bit ? (type | 16) : type); 1885 Name = name,
1886 Type = type.Value,
1887 Win64 = search64bit
1888 };
1889
1890 this.Core.AddTuple(tuple);
1810 } 1891 }
1811 1892
1812 return signature; 1893 return signature;
@@ -2017,8 +2098,7 @@ namespace WixToolset.Core
2017 2098
2018 if (!this.Core.EncounteredError) 2099 if (!this.Core.EncounteredError)
2019 { 2100 {
2020 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.CCPSearch); 2101 this.Core.AddTuple(new CCPSearchTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, signature)));
2021 row.Set(0, signature);
2022 } 2102 }
2023 } 2103 }
2024 2104
@@ -2044,7 +2124,7 @@ namespace WixToolset.Core
2044 var guid = "*"; 2124 var guid = "*";
2045 var componentIdPlaceholder = String.Format(Compiler.DefaultComponentIdPlaceholderFormat, this.componentIdPlaceholdersResolver.VariableCount); // placeholder id for defaulting Component/@Id to keypath id. 2125 var componentIdPlaceholder = String.Format(Compiler.DefaultComponentIdPlaceholderFormat, this.componentIdPlaceholdersResolver.VariableCount); // placeholder id for defaulting Component/@Id to keypath id.
2046 var componentIdPlaceholderWixVariable = String.Format(Compiler.DefaultComponentIdPlaceholderWixVariableFormat, componentIdPlaceholder); 2126 var componentIdPlaceholderWixVariable = String.Format(Compiler.DefaultComponentIdPlaceholderWixVariableFormat, componentIdPlaceholder);
2047 var id = new Identifier(componentIdPlaceholderWixVariable, AccessModifier.Private); 2127 var id = new Identifier(AccessModifier.Private, componentIdPlaceholderWixVariable);
2048 var keyFound = false; 2128 var keyFound = false;
2049 string keyPath = null; 2129 string keyPath = null;
2050 var shouldAddCreateFolder = false; 2130 var shouldAddCreateFolder = false;
@@ -2402,9 +2482,13 @@ namespace WixToolset.Core
2402 2482
2403 if (shouldAddCreateFolder) 2483 if (shouldAddCreateFolder)
2404 { 2484 {
2405 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.CreateFolder, new Identifier(AccessModifier.Public, directoryId, id.Id)); 2485 var tuple = new CreateFolderTuple(sourceLineNumbers)
2406 row.Set(0, directoryId); 2486 {
2407 row.Set(1, id.Id); 2487 Directory_ = directoryId,
2488 Component_ = id.Id
2489 };
2490
2491 this.Core.AddTuple(tuple);
2408 } 2492 }
2409 2493
2410 // check for conditions that exclude this component from using generated guids 2494 // check for conditions that exclude this component from using generated guids
@@ -2439,7 +2523,7 @@ namespace WixToolset.Core
2439 { 2523 {
2440 this.componentIdPlaceholdersResolver.AddVariable(sourceLineNumbers, componentIdPlaceholder, keyPath, false); 2524 this.componentIdPlaceholdersResolver.AddVariable(sourceLineNumbers, componentIdPlaceholder, keyPath, false);
2441 2525
2442 id = new Identifier(keyPath, AccessModifier.Private); 2526 id = new Identifier(AccessModifier.Private, keyPath);
2443 } 2527 }
2444 else 2528 else
2445 { 2529 {
@@ -2458,7 +2542,6 @@ namespace WixToolset.Core
2458 { 2542 {
2459 var tuple = new ComponentTuple(sourceLineNumbers, id) 2543 var tuple = new ComponentTuple(sourceLineNumbers, id)
2460 { 2544 {
2461 Component = id.Id,
2462 ComponentId = guid, 2545 ComponentId = guid,
2463 Directory_ = directoryId, 2546 Directory_ = directoryId,
2464 Location = location, 2547 Location = location,
@@ -2472,35 +2555,29 @@ namespace WixToolset.Core
2472 Shared = shared, 2555 Shared = shared,
2473 Transitive = transitive, 2556 Transitive = transitive,
2474 UninstallWhenSuperseded = uninstallWhenSuperseded, 2557 UninstallWhenSuperseded = uninstallWhenSuperseded,
2475 Win64 = win64, 2558 Win64 = win64
2476 }; 2559 };
2477 2560
2478 this.Core.AddTuple(tuple); 2561 this.Core.AddTuple(tuple);
2479 2562
2480 //var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Component, id);
2481 //row.Set(1, guid);
2482 //row.Set(2, directoryId);
2483 //row.Set(3, bits | keyBits);
2484 //row.Set(4, condition);
2485 //row.Set(5, keyPath);
2486
2487 if (multiInstance) 2563 if (multiInstance)
2488 { 2564 {
2489 //var instanceComponentRow = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixInstanceComponent, id); 2565 this.Core.AddTuple(new WixInstanceComponentTuple(sourceLineNumbers, id)
2490
2491 var instanceComponentTuple = new WixInstanceComponentTuple(sourceLineNumbers, id)
2492 { 2566 {
2493 Component_ = id.Id, 2567 Component_ = id.Id,
2494 }; 2568 });
2495
2496 this.Core.AddTuple(instanceComponentTuple);
2497 } 2569 }
2498 2570
2499 if (0 < symbols.Count) 2571 if (0 < symbols.Count)
2500 { 2572 {
2501 var symbolRow = (WixDeltaPatchSymbolPathsTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixDeltaPatchSymbolPaths, id); 2573 var tupleDelaPatch = new WixDeltaPatchSymbolPathsTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, SymbolPathType.Component, id.Id))
2502 symbolRow.Type = SymbolPathType.Component; 2574 {
2503 symbolRow.SymbolPaths = String.Join(";", symbols); 2575 SymbolType = SymbolPathType.Component,
2576 SymbolId = id.Id,
2577 SymbolPaths = String.Join(";", symbols)
2578 };
2579
2580 this.Core.AddTuple(tupleDelaPatch);
2504 } 2581 }
2505 2582
2506 // Complus 2583 // Complus
@@ -2607,7 +2684,7 @@ namespace WixToolset.Core
2607 2684
2608 if (!this.Core.EncounteredError) 2685 if (!this.Core.EncounteredError)
2609 { 2686 {
2610 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixComponentGroup, id); 2687 this.Core.AddTuple(new WixComponentGroupTuple(sourceLineNumbers, id));
2611 2688
2612 // Add this componentGroup and its parent in WixGroup. 2689 // Add this componentGroup and its parent in WixGroup.
2613 this.Core.CreateWixGroupRow(sourceLineNumbers, parentType, parentId, ComplexReferenceChildType.ComponentGroup, id.Id); 2690 this.Core.CreateWixGroupRow(sourceLineNumbers, parentType, parentId, ComplexReferenceChildType.ComponentGroup, id.Id);
@@ -2802,7 +2879,7 @@ namespace WixToolset.Core
2802 } 2879 }
2803 oneChild = true; 2880 oneChild = true;
2804 signature = this.ParseFileSearchElement(child, id.Id, false, CompilerConstants.IntegerNotSet); 2881 signature = this.ParseFileSearchElement(child, id.Id, false, CompilerConstants.IntegerNotSet);
2805 id = new Identifier(signature, AccessModifier.Private); // FileSearch signatures override parent signatures 2882 id = new Identifier(AccessModifier.Private, signature); // FileSearch signatures override parent signatures
2806 break; 2883 break;
2807 case "FileSearchRef": 2884 case "FileSearchRef":
2808 if (oneChild) 2885 if (oneChild)
@@ -2811,7 +2888,7 @@ namespace WixToolset.Core
2811 } 2888 }
2812 oneChild = true; 2889 oneChild = true;
2813 var newId = this.ParseSimpleRefElement(child, "Signature"); // FileSearch signatures override parent signatures 2890 var newId = this.ParseSimpleRefElement(child, "Signature"); // FileSearch signatures override parent signatures
2814 id = new Identifier(newId, AccessModifier.Private); 2891 id = new Identifier(AccessModifier.Private, newId);
2815 signature = null; 2892 signature = null;
2816 break; 2893 break;
2817 default: 2894 default:
@@ -2903,9 +2980,13 @@ namespace WixToolset.Core
2903 2980
2904 if (!this.Core.EncounteredError) 2981 if (!this.Core.EncounteredError)
2905 { 2982 {
2906 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.CreateFolder, new Identifier(AccessModifier.Public, directoryId, componentId)); 2983 var tuple = new CreateFolderTuple(sourceLineNumbers)
2907 row.Set(0, directoryId); 2984 {
2908 row.Set(1, componentId); 2985 Directory_ = directoryId,
2986 Component_ = componentId
2987 };
2988
2989 this.Core.AddTuple(tuple);
2909 } 2990 }
2910 2991
2911 return directoryId; 2992 return directoryId;
@@ -3026,32 +3107,17 @@ namespace WixToolset.Core
3026 3107
3027 if (!this.Core.EncounteredError) 3108 if (!this.Core.EncounteredError)
3028 { 3109 {
3029 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MoveFile, id); 3110 var tuple = new MoveFileTuple(sourceLineNumbers, id)
3030 row.Set(1, componentId);
3031 row.Set(2, sourceName);
3032 row.Set(3, String.IsNullOrEmpty(destinationShortName) && String.IsNullOrEmpty(destinationName) ? null : this.GetMsiFilenameValue(destinationShortName, destinationName));
3033 if (null != sourceDirectory)
3034 {
3035 row.Set(4, sourceDirectory);
3036 }
3037 else if (null != sourceProperty)
3038 { 3111 {
3039 row.Set(4, sourceProperty); 3112 Component_ = componentId,
3040 } 3113 SourceName = sourceName,
3041 else 3114 DestName= String.IsNullOrEmpty(destinationShortName) && String.IsNullOrEmpty(destinationName) ? null : this.GetMsiFilenameValue(destinationShortName, destinationName),
3042 { 3115 SourceFolder = sourceDirectory ?? sourceProperty,
3043 row.Set(4, sourceFolder); 3116 DestFolder = destinationDirectory ?? destinationProperty,
3044 } 3117 Delete = delete
3118 };
3045 3119
3046 if (null != destinationDirectory) 3120 this.Core.AddTuple(tuple);
3047 {
3048 row.Set(5, destinationDirectory);
3049 }
3050 else
3051 {
3052 row.Set(5, destinationProperty);
3053 }
3054 row.Set(6, delete ? 1 : 0);
3055 } 3121 }
3056 } 3122 }
3057 else // copy the file 3123 else // copy the file
@@ -3088,18 +3154,15 @@ namespace WixToolset.Core
3088 3154
3089 if (!this.Core.EncounteredError) 3155 if (!this.Core.EncounteredError)
3090 { 3156 {
3091 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.DuplicateFile, id); 3157 var tuple = new DuplicateFileTuple(sourceLineNumbers, id)
3092 row.Set(1, componentId);
3093 row.Set(2, fileId);
3094 row.Set(3, String.IsNullOrEmpty(destinationShortName) && String.IsNullOrEmpty(destinationName) ? null : this.GetMsiFilenameValue(destinationShortName, destinationName));
3095 if (null != destinationDirectory)
3096 {
3097 row.Set(4, destinationDirectory);
3098 }
3099 else
3100 { 3158 {
3101 row.Set(4, destinationProperty); 3159 Component_ = componentId,
3102 } 3160 File_ = fileId,
3161 DestName = String.IsNullOrEmpty(destinationShortName) && String.IsNullOrEmpty(destinationName) ? null : this.GetMsiFilenameValue(destinationShortName, destinationName),
3162 DestFolder = destinationDirectory ?? destinationProperty
3163 };
3164
3165 this.Core.AddTuple(tuple);
3103 } 3166 }
3104 } 3167 }
3105 } 3168 }
@@ -3499,20 +3562,12 @@ namespace WixToolset.Core
3499 TSAware = tsAware, 3562 TSAware = tsAware,
3500 Win64 = win64, 3563 Win64 = win64,
3501 }; 3564 };
3502 //var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.CustomAction, id);
3503 //row.Set(1, bits | sourceBits | targetBits);
3504 //row.Set(2, source);
3505 //row.Set(3, target);
3506 //if (0 != extendedBits)
3507 //{
3508 // row.Set(4, extendedBits);
3509 //}
3510 3565
3511 this.Core.AddTuple(tuple); 3566 this.Core.AddTuple(tuple);
3512 3567
3513 if (YesNoType.Yes == suppressModularization) 3568 if (YesNoType.Yes == suppressModularization)
3514 { 3569 {
3515 this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixSuppressModularization, id); 3570 this.Core.AddTuple(new WixSuppressModularizationTuple(sourceLineNumbers, id));
3516 } 3571 }
3517 3572
3518 // For deferred CAs that specify HideTarget we should also hide the CA data property for the action. 3573 // For deferred CAs that specify HideTarget we should also hide the CA data property for the action.
@@ -3619,124 +3674,6 @@ namespace WixToolset.Core
3619 } 3674 }
3620 3675
3621 /// <summary> 3676 /// <summary>
3622 /// Parses a PatchFamilyGroup element.
3623 /// </summary>
3624 /// <param name="node">Element to parse.</param>
3625 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
3626 private void ParsePatchFamilyGroupElement(XElement node, ComplexReferenceParentType parentType, string parentId)
3627 {
3628 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
3629 Identifier id = null;
3630
3631 foreach (var attrib in node.Attributes())
3632 {
3633 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
3634 {
3635 switch (attrib.Name.LocalName)
3636 {
3637 case "Id":
3638 id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib);
3639 break;
3640 default:
3641 this.Core.UnexpectedAttribute(node, attrib);
3642 break;
3643 }
3644 }
3645 else
3646 {
3647 this.Core.ParseExtensionAttribute(node, attrib);
3648 }
3649 }
3650
3651 if (null == id)
3652 {
3653 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
3654 id = Identifier.Invalid;
3655 }
3656
3657 foreach (var child in node.Elements())
3658 {
3659 if (CompilerCore.WixNamespace == child.Name.Namespace)
3660 {
3661 switch (child.Name.LocalName)
3662 {
3663 case "PatchFamily":
3664 this.ParsePatchFamilyElement(child, ComplexReferenceParentType.PatchFamilyGroup, id.Id);
3665 break;
3666 case "PatchFamilyRef":
3667 this.ParsePatchFamilyRefElement(child, ComplexReferenceParentType.PatchFamilyGroup, id.Id);
3668 break;
3669 case "PatchFamilyGroupRef":
3670 this.ParsePatchFamilyGroupRefElement(child, ComplexReferenceParentType.PatchFamilyGroup, id.Id);
3671 break;
3672 default:
3673 this.Core.UnexpectedElement(node, child);
3674 break;
3675 }
3676 }
3677 else
3678 {
3679 this.Core.ParseExtensionElement(node, child);
3680 }
3681 }
3682
3683 if (!this.Core.EncounteredError)
3684 {
3685 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixPatchFamilyGroup, id);
3686
3687 //Add this PatchFamilyGroup and its parent in WixGroup.
3688 this.Core.CreateWixGroupRow(sourceLineNumbers, parentType, parentId, ComplexReferenceChildType.PatchFamilyGroup, id.Id);
3689 }
3690 }
3691
3692 /// <summary>
3693 /// Parses a PatchFamilyGroup reference element.
3694 /// </summary>
3695 /// <param name="node">Element to parse.</param>
3696 /// <param name="parentType">The type of parent.</param>
3697 /// <param name="parentId">Identifier of parent element.</param>
3698 private void ParsePatchFamilyGroupRefElement(XElement node, ComplexReferenceParentType parentType, string parentId)
3699 {
3700 Debug.Assert(ComplexReferenceParentType.PatchFamilyGroup == parentType || ComplexReferenceParentType.Patch == parentType);
3701
3702 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
3703 string id = null;
3704
3705 foreach (var attrib in node.Attributes())
3706 {
3707 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
3708 {
3709 switch (attrib.Name.LocalName)
3710 {
3711 case "Id":
3712 id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
3713 this.Core.CreateSimpleReference(sourceLineNumbers, "WixPatchFamilyGroup", id);
3714 break;
3715 default:
3716 this.Core.UnexpectedAttribute(node, attrib);
3717 break;
3718 }
3719 }
3720 else
3721 {
3722 this.Core.ParseExtensionAttribute(node, attrib);
3723 }
3724 }
3725
3726 if (null == id)
3727 {
3728 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
3729 }
3730
3731 this.Core.ParseForExtensionElements(node);
3732
3733 if (!this.Core.EncounteredError)
3734 {
3735 this.Core.CreateComplexReference(sourceLineNumbers, parentType, parentId, null, ComplexReferenceChildType.PatchFamilyGroup, id, true);
3736 }
3737 }
3738
3739 /// <summary>
3740 /// Parses an ensure table element. 3677 /// Parses an ensure table element.
3741 /// </summary> 3678 /// </summary>
3742 /// <param name="node">Element to parse.</param> 3679 /// <param name="node">Element to parse.</param>
@@ -4022,9 +3959,11 @@ namespace WixToolset.Core
4022 3959
4023 if (!this.Core.EncounteredError) 3960 if (!this.Core.EncounteredError)
4024 { 3961 {
4025 var rowRow = this.Core.CreateRow(childSourceLineNumbers, TupleDefinitionType.WixCustomRow); 3962 this.Core.AddTuple(new WixCustomRowTuple(childSourceLineNumbers)
4026 rowRow.Set(0, tableId); 3963 {
4027 rowRow.Set(1, dataValue); 3964 Table = tableId,
3965 FieldData = dataValue
3966 });
4028 } 3967 }
4029 break; 3968 break;
4030 default: 3969 default:
@@ -4047,21 +3986,24 @@ namespace WixToolset.Core
4047 3986
4048 if (!this.Core.EncounteredError) 3987 if (!this.Core.EncounteredError)
4049 { 3988 {
4050 var id = new Identifier(tableId, AccessModifier.Public); 3989 var tuple = new WixCustomTableTuple(sourceLineNumbers, new Identifier(AccessModifier.Public, tableId))
4051 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixCustomTable, id); 3990 {
4052 row.Set(1, columnCount); 3991 ColumnCount = columnCount,
4053 row.Set(2, columnNames); 3992 ColumnNames = columnNames,
4054 row.Set(3, columnTypes); 3993 ColumnTypes = columnTypes,
4055 row.Set(4, primaryKeys); 3994 PrimaryKeys = primaryKeys,
4056 row.Set(5, minValues); 3995 MinValues = minValues,
4057 row.Set(6, maxValues); 3996 MaxValues = maxValues,
4058 row.Set(7, keyTables); 3997 KeyTables = keyTables,
4059 row.Set(8, keyColumns); 3998 KeyColumns = keyColumns,
4060 row.Set(9, categories); 3999 Categories = categories,
4061 row.Set(10, sets); 4000 Sets = sets,
4062 row.Set(11, descriptions); 4001 Descriptions = descriptions,
4063 row.Set(12, modularizations); 4002 Modularizations = modularizations,
4064 row.Set(13, bootstrapperApplicationData ? 1 : 0); 4003 BootstrapperApplicationData = bootstrapperApplicationData
4004 };
4005
4006 this.Core.AddTuple(tuple);
4065 } 4007 }
4066 } 4008 }
4067 } 4009 }
@@ -4315,22 +4257,23 @@ namespace WixToolset.Core
4315 4257
4316 if (!this.Core.EncounteredError) 4258 if (!this.Core.EncounteredError)
4317 { 4259 {
4318 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Directory, id); 4260 var tuple = new DirectoryTuple(sourceLineNumbers, id)
4319 row.Set(1, parentId);
4320 row.Set(2, defaultDir);
4321
4322 if (null != componentGuidGenerationSeed)
4323 { 4261 {
4324 var wixRow = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixDirectory); 4262 Directory_Parent = parentId,
4325 wixRow.Set(0, id.Id); 4263 DefaultDir = defaultDir,
4326 wixRow.Set(1, componentGuidGenerationSeed); 4264 ComponentGuidGenerationSeed = componentGuidGenerationSeed
4327 } 4265 };
4266
4267 this.Core.AddTuple(tuple);
4328 4268
4329 if (null != symbols) 4269 if (null != symbols)
4330 { 4270 {
4331 var symbolRow = (WixDeltaPatchSymbolPathsTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixDeltaPatchSymbolPaths, id); 4271 this.Core.AddTuple(new WixDeltaPatchSymbolPathsTuple(sourceLineNumbers, id)
4332 symbolRow.Type = SymbolPathType.Directory; 4272 {
4333 symbolRow.SymbolPaths = symbols; 4273 SymbolType = SymbolPathType.Directory,
4274 SymbolId = id.Id,
4275 SymbolPaths = symbols,
4276 });
4334 } 4277 }
4335 } 4278 }
4336 } 4279 }
@@ -4547,14 +4490,19 @@ namespace WixToolset.Core
4547 signature = id.Id; 4490 signature = id.Id;
4548 } 4491 }
4549 4492
4550 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.DrLocator, new Identifier(access, rowId, parentSignature, path)); 4493 var tuple = new DrLocatorTuple(sourceLineNumbers)
4551 row.Set(0, rowId); 4494 {
4552 row.Set(1, parentSignature); 4495 Signature_ = rowId,
4553 row.Set(2, path); 4496 Parent = parentSignature,
4497 Path = path,
4498 };
4499
4554 if (CompilerConstants.IntegerNotSet != depth) 4500 if (CompilerConstants.IntegerNotSet != depth)
4555 { 4501 {
4556 row.Set(3, depth); 4502 tuple.Depth = depth;
4557 } 4503 }
4504
4505 this.Core.AddTuple(tuple);
4558 } 4506 }
4559 4507
4560 return signature; 4508 return signature;
@@ -5144,7 +5092,7 @@ namespace WixToolset.Core
5144 5092
5145 if (!this.Core.EncounteredError) 5093 if (!this.Core.EncounteredError)
5146 { 5094 {
5147 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixFeatureGroup, id); 5095 this.Core.AddTuple(new WixFeatureGroupTuple(sourceLineNumbers, id));
5148 5096
5149 //Add this FeatureGroup and its parent in WixGroup. 5097 //Add this FeatureGroup and its parent in WixGroup.
5150 this.Core.CreateWixGroupRow(sourceLineNumbers, parentType, parentId, ComplexReferenceChildType.FeatureGroup, id.Id); 5098 this.Core.CreateWixGroupRow(sourceLineNumbers, parentType, parentId, ComplexReferenceChildType.FeatureGroup, id.Id);
@@ -5403,8 +5351,13 @@ namespace WixToolset.Core
5403 5351
5404 if (!this.Core.EncounteredError) 5352 if (!this.Core.EncounteredError)
5405 { 5353 {
5406 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Error, new Identifier(AccessModifier.Public, id)); 5354 var tuple = new ErrorTuple(sourceLineNumbers)
5407 row.Set(1, Common.GetInnerText(node)); // TODO: * 5355 {
5356 Error = id,
5357 Message = Common.GetInnerText(node)
5358 };
5359
5360 this.Core.AddTuple(tuple);
5408 } 5361 }
5409 } 5362 }
5410 5363
@@ -5490,12 +5443,16 @@ namespace WixToolset.Core
5490 { 5443 {
5491 if (!this.Core.EncounteredError) 5444 if (!this.Core.EncounteredError)
5492 { 5445 {
5493 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Extension); 5446 var tuple = new ExtensionTuple(sourceLineNumbers, new Identifier(AccessModifier.Public, extension, componentId))
5494 row.Set(0, extension); 5447 {
5495 row.Set(1, componentId); 5448 Extension = extension,
5496 row.Set(2, progId); 5449 Component_ = componentId,
5497 row.Set(3, mime); 5450 ProgId_ = progId,
5498 row.Set(4, Guid.Empty.ToString("B")); 5451 MIME_ = mime,
5452 Feature_ = Guid.Empty.ToString("B")
5453 };
5454
5455 this.Core.AddTuple(tuple);
5499 5456
5500 this.Core.EnsureTable(sourceLineNumbers, "Verb"); 5457 this.Core.EnsureTable(sourceLineNumbers, "Verb");
5501 } 5458 }
@@ -5560,7 +5517,7 @@ namespace WixToolset.Core
5560 string symbols = null; 5517 string symbols = null;
5561 5518
5562 string procArch = null; 5519 string procArch = null;
5563 var selfRegCost = CompilerConstants.IntegerNotSet; 5520 int? selfRegCost = null;
5564 string shortName = null; 5521 string shortName = null;
5565 var source = sourcePath; // assume we'll use the parents as the source for this file 5522 var source = sourcePath; // assume we'll use the parents as the source for this file
5566 var sourceSet = false; 5523 var sourceSet = false;
@@ -5914,30 +5871,29 @@ namespace WixToolset.Core
5914 } 5871 }
5915 } 5872 }
5916 5873
5917 var fileRow = (FileTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.File, id); 5874 var tuple = new FileTuple(sourceLineNumbers, id)
5918 fileRow.Component_ = componentId;
5919 //fileRow.FileName = GetMsiFilenameValue(shortName, name);
5920 fileRow.ShortFileName = shortName;
5921 fileRow.LongFileName = name;
5922 fileRow.FileSize = defaultSize;
5923 if (null != companionFile)
5924 {
5925 fileRow.Version = companionFile;
5926 }
5927 else if (null != defaultVersion)
5928 { 5875 {
5929 fileRow.Version = defaultVersion; 5876 Component_ = componentId,
5930 } 5877 ShortFileName = shortName,
5931 fileRow.Language = defaultLanguage; 5878 LongFileName = name,
5932 fileRow.ReadOnly = readOnly; 5879 FileSize = defaultSize,
5933 fileRow.Checksum = checksum; 5880 Version = companionFile ?? defaultVersion,
5934 fileRow.Compressed = compressed; 5881 Language = defaultLanguage,
5935 fileRow.Hidden = hidden; 5882 ReadOnly = readOnly,
5936 fileRow.System = system; 5883 Hidden = hidden,
5937 fileRow.Vital = vital; 5884 System = system,
5938 // the Sequence row is set in the binder 5885 Vital = vital,
5886 Checksum = checksum,
5887 Compressed = compressed,
5888 FontTitle = fontTitle,
5889 SelfRegCost = selfRegCost,
5890 BindPath = bindPath,
5891 };
5892
5893 this.Core.AddTuple(tuple);
5939 5894
5940 var wixFileRow = (WixFileTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixFile, id); 5895 // TODO: Remove all this.
5896 var wixFileRow = (WixFileTuple)this.Core.CreateTuple(sourceLineNumbers, TupleDefinitionType.WixFile, id);
5941 wixFileRow.AssemblyType = assemblyType; 5897 wixFileRow.AssemblyType = assemblyType;
5942 wixFileRow.File_AssemblyManifest = assemblyManifest; 5898 wixFileRow.File_AssemblyManifest = assemblyManifest;
5943 wixFileRow.File_AssemblyApplication = assemblyApplication; 5899 wixFileRow.File_AssemblyApplication = assemblyApplication;
@@ -5951,50 +5907,34 @@ namespace WixToolset.Core
5951 5907
5952 // Always create a delta patch row for this file since other elements (like Component and Media) may 5908 // Always create a delta patch row for this file since other elements (like Component and Media) may
5953 // want to add symbol paths to it. 5909 // want to add symbol paths to it.
5954 var deltaPatchFileRow = (WixDeltaPatchFileTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixDeltaPatchFile, id); 5910 this.Core.AddTuple(new WixDeltaPatchFileTuple(sourceLineNumbers, id)
5955 deltaPatchFileRow.RetainLengths = protectLengths; 5911 {
5956 deltaPatchFileRow.IgnoreOffsets = ignoreOffsets; 5912 RetainLengths = protectLengths,
5957 deltaPatchFileRow.IgnoreLengths = ignoreLengths; 5913 IgnoreOffsets = ignoreOffsets,
5958 deltaPatchFileRow.RetainOffsets = protectOffsets; 5914 IgnoreLengths = ignoreLengths,
5915 RetainOffsets = protectOffsets
5916 });
5959 5917
5960 if (null != symbols) 5918 if (null != symbols)
5961 { 5919 {
5962 var symbolRow = (WixDeltaPatchSymbolPathsTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixDeltaPatchSymbolPaths, id); 5920 this.Core.AddTuple(new WixDeltaPatchSymbolPathsTuple(sourceLineNumbers)
5963 symbolRow.Type = SymbolPathType.File; 5921 {
5964 symbolRow.SymbolPaths = symbols; 5922 SymbolType = SymbolPathType.File,
5923 SymbolId = id.Id,
5924 SymbolPaths = symbols
5925 });
5965 } 5926 }
5966 5927
5967 if (FileAssemblyType.NotAnAssembly != assemblyType) 5928 if (FileAssemblyType.NotAnAssembly != assemblyType)
5968 { 5929 {
5969 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiAssembly); 5930 this.Core.AddTuple(new MsiAssemblyTuple(sourceLineNumbers)
5970 row.Set(0, componentId); 5931 {
5971 row.Set(1, Guid.Empty.ToString("B")); 5932 Component_ = componentId,
5972 row.Set(2, assemblyManifest); 5933 Feature_ = Guid.Empty.ToString("B"),
5973 row.Set(3, assemblyApplication); 5934 File_Manifest = assemblyManifest,
5974 row.Set(4, (FileAssemblyType.DotNetAssembly == assemblyType) ? 0 : 1); 5935 File_Application = assemblyApplication,
5975 } 5936 Type = assemblyType
5976 5937 });
5977 if (null != bindPath)
5978 {
5979 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.BindImage);
5980 row.Set(0, id.Id);
5981 row.Set(1, bindPath);
5982
5983 // TODO: technically speaking each of the properties in the "bindPath" should be added as references, but how much do we really care about BindImage?
5984 }
5985
5986 if (CompilerConstants.IntegerNotSet != selfRegCost)
5987 {
5988 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.SelfReg);
5989 row.Set(0, id.Id);
5990 row.Set(1, selfRegCost);
5991 }
5992
5993 if (null != fontTitle)
5994 {
5995 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Font);
5996 row.Set(0, id.Id);
5997 row.Set(1, fontTitle);
5998 } 5938 }
5999 } 5939 }
6000 5940
@@ -6110,7 +6050,7 @@ namespace WixToolset.Core
6110 } 6050 }
6111 else // reuse parent signature in the Signature table 6051 else // reuse parent signature in the Signature table
6112 { 6052 {
6113 id = new Identifier(parentSignature, AccessModifier.Private); 6053 id = new Identifier(AccessModifier.Private, parentSignature);
6114 } 6054 }
6115 } 6055 }
6116 6056
@@ -6138,28 +6078,35 @@ namespace WixToolset.Core
6138 6078
6139 if (!this.Core.EncounteredError) 6079 if (!this.Core.EncounteredError)
6140 { 6080 {
6141 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Signature, id); 6081 var tuple = new SignatureTuple(sourceLineNumbers, id)
6142 row.Set(1, name ?? shortName); 6082 {
6143 row.Set(2, minVersion); 6083 FileName = name ?? shortName,
6144 row.Set(3, maxVersion); 6084 MinVersion = minVersion,
6085 MaxVersion = maxVersion,
6086 Languages = languages
6087 };
6145 6088
6146 if (CompilerConstants.IntegerNotSet != minSize) 6089 if (CompilerConstants.IntegerNotSet != minSize)
6147 { 6090 {
6148 row.Set(4, minSize); 6091 tuple.MinSize = minSize;
6149 } 6092 }
6093
6150 if (CompilerConstants.IntegerNotSet != maxSize) 6094 if (CompilerConstants.IntegerNotSet != maxSize)
6151 { 6095 {
6152 row.Set(5, maxSize); 6096 tuple.MaxSize = maxSize;
6153 } 6097 }
6098
6154 if (CompilerConstants.IntegerNotSet != minDate) 6099 if (CompilerConstants.IntegerNotSet != minDate)
6155 { 6100 {
6156 row.Set(6, minDate); 6101 tuple.MinDate = minDate;
6157 } 6102 }
6103
6158 if (CompilerConstants.IntegerNotSet != maxDate) 6104 if (CompilerConstants.IntegerNotSet != maxDate)
6159 { 6105 {
6160 row.Set(7, maxDate); 6106 tuple.MaxDate = maxDate;
6161 } 6107 }
6162 row.Set(8, languages); 6108
6109 this.Core.AddTuple(tuple);
6163 6110
6164 // Create a DrLocator row to associate the file with a directory 6111 // Create a DrLocator row to associate the file with a directory
6165 // when a different identifier is specified for the FileSearch. 6112 // when a different identifier is specified for the FileSearch.
@@ -6169,15 +6116,19 @@ namespace WixToolset.Core
6169 { 6116 {
6170 // Creates the DrLocator row for the directory search while 6117 // Creates the DrLocator row for the directory search while
6171 // the parent DirectorySearch creates the file locator row. 6118 // the parent DirectorySearch creates the file locator row.
6172 row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.DrLocator, new Identifier(AccessModifier.Public, parentSignature, id.Id, String.Empty)); 6119 this.Core.AddTuple(new DrLocatorTuple(sourceLineNumbers, new Identifier(AccessModifier.Public, parentSignature, id.Id, String.Empty))
6173 row.Set(0, parentSignature); 6120 {
6174 row.Set(1, id.Id); 6121 Signature_ = parentSignature,
6122 Parent = id.Id
6123 });
6175 } 6124 }
6176 else 6125 else
6177 { 6126 {
6178 row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.DrLocator, new Identifier(AccessModifier.Public, id.Id, parentSignature, String.Empty)); 6127 this.Core.AddTuple(new DrLocatorTuple(sourceLineNumbers, new Identifier(AccessModifier.Public, id.Id, parentSignature, String.Empty))
6179 row.Set(0, id.Id); 6128 {
6180 row.Set(1, parentSignature); 6129 Signature_ = id.Id,
6130 Parent = parentSignature
6131 });
6181 } 6132 }
6182 } 6133 }
6183 } 6134 }
@@ -6193,7 +6144,7 @@ namespace WixToolset.Core
6193 private void ParseFragmentElement(XElement node) 6144 private void ParseFragmentElement(XElement node)
6194 { 6145 {
6195 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); 6146 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
6196 string id = null; 6147 Identifier id = null;
6197 6148
6198 this.activeName = null; 6149 this.activeName = null;
6199 this.activeLanguage = null; 6150 this.activeLanguage = null;
@@ -6205,7 +6156,7 @@ namespace WixToolset.Core
6205 switch (attrib.Name.LocalName) 6156 switch (attrib.Name.LocalName)
6206 { 6157 {
6207 case "Id": 6158 case "Id":
6208 id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); 6159 id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib);
6209 break; 6160 break;
6210 default: 6161 default:
6211 this.Core.UnexpectedAttribute(node, attrib); 6162 this.Core.UnexpectedAttribute(node, attrib);
@@ -6220,7 +6171,7 @@ namespace WixToolset.Core
6220 6171
6221 // NOTE: Id is not required for Fragments, this is a departure from the normal run of the mill processing. 6172 // NOTE: Id is not required for Fragments, this is a departure from the normal run of the mill processing.
6222 6173
6223 this.Core.CreateActiveSection(id, SectionType.Fragment, 0, this.Context.CompilationId); 6174 this.Core.CreateActiveSection(id?.Id, SectionType.Fragment, 0, this.Context.CompilationId);
6224 6175
6225 var featureDisplay = 0; 6176 var featureDisplay = 0;
6226 foreach (var child in node.Elements()) 6177 foreach (var child in node.Elements())
@@ -6232,19 +6183,19 @@ namespace WixToolset.Core
6232 case "_locDefinition": 6183 case "_locDefinition":
6233 break; 6184 break;
6234 case "AdminExecuteSequence": 6185 case "AdminExecuteSequence":
6235 this.ParseSequenceElement(child, child.Name.LocalName); 6186 this.ParseSequenceElement(child, SequenceTable.AdminExecuteSequence);
6236 break; 6187 break;
6237 case "AdminUISequence": 6188 case "AdminUISequence":
6238 this.ParseSequenceElement(child, child.Name.LocalName); 6189 this.ParseSequenceElement(child, SequenceTable.AdminUISequence);
6239 break; 6190 break;
6240 case "AdvertiseExecuteSequence": 6191 case "AdvertiseExecuteSequence":
6241 this.ParseSequenceElement(child, child.Name.LocalName); 6192 this.ParseSequenceElement(child, SequenceTable.AdvertiseExecuteSequence);
6242 break; 6193 break;
6243 case "InstallExecuteSequence": 6194 case "InstallExecuteSequence":
6244 this.ParseSequenceElement(child, child.Name.LocalName); 6195 this.ParseSequenceElement(child, SequenceTable.InstallExecuteSequence);
6245 break; 6196 break;
6246 case "InstallUISequence": 6197 case "InstallUISequence":
6247 this.ParseSequenceElement(child, child.Name.LocalName); 6198 this.ParseSequenceElement(child, SequenceTable.InstallUISequence);
6248 break; 6199 break;
6249 case "AppId": 6200 case "AppId":
6250 this.ParseAppIdElement(child, null, YesNoType.Yes, null, null, null); 6201 this.ParseAppIdElement(child, null, YesNoType.Yes, null, null, null);
@@ -6265,7 +6216,7 @@ namespace WixToolset.Core
6265 this.ParseComponentElement(child, ComplexReferenceParentType.Unknown, null, null, CompilerConstants.IntegerNotSet, null, null); 6216 this.ParseComponentElement(child, ComplexReferenceParentType.Unknown, null, null, CompilerConstants.IntegerNotSet, null, null);
6266 break; 6217 break;
6267 case "ComponentGroup": 6218 case "ComponentGroup":
6268 this.ParseComponentGroupElement(child, ComplexReferenceParentType.Unknown, id); 6219 this.ParseComponentGroupElement(child, ComplexReferenceParentType.Unknown, id?.Id);
6269 break; 6220 break;
6270 case "Condition": 6221 case "Condition":
6271 this.ParseConditionElement(child, node.Name.LocalName, null, null); 6222 this.ParseConditionElement(child, node.Name.LocalName, null, null);
@@ -6301,7 +6252,7 @@ namespace WixToolset.Core
6301 this.ParseFeatureElement(child, ComplexReferenceParentType.Unknown, null, ref featureDisplay); 6252 this.ParseFeatureElement(child, ComplexReferenceParentType.Unknown, null, ref featureDisplay);
6302 break; 6253 break;
6303 case "FeatureGroup": 6254 case "FeatureGroup":
6304 this.ParseFeatureGroupElement(child, ComplexReferenceParentType.Unknown, id); 6255 this.ParseFeatureGroupElement(child, ComplexReferenceParentType.Unknown, id.Id);
6305 break; 6256 break;
6306 case "FeatureRef": 6257 case "FeatureRef":
6307 this.ParseFeatureRefElement(child, ComplexReferenceParentType.Unknown, null); 6258 this.ParseFeatureRefElement(child, ComplexReferenceParentType.Unknown, null);
@@ -6326,13 +6277,13 @@ namespace WixToolset.Core
6326 this.ParseCertificatesElement(child); 6277 this.ParseCertificatesElement(child);
6327 break; 6278 break;
6328 case "PatchFamily": 6279 case "PatchFamily":
6329 this.ParsePatchFamilyElement(child, ComplexReferenceParentType.Unknown, id); 6280 this.ParsePatchFamilyElement(child, ComplexReferenceParentType.Unknown, id.Id);
6330 break; 6281 break;
6331 case "PatchFamilyGroup": 6282 case "PatchFamilyGroup":
6332 this.ParsePatchFamilyGroupElement(child, ComplexReferenceParentType.Unknown, id); 6283 this.ParsePatchFamilyGroupElement(child, ComplexReferenceParentType.Unknown, id.Id);
6333 break; 6284 break;
6334 case "PatchFamilyGroupRef": 6285 case "PatchFamilyGroupRef":
6335 this.ParsePatchFamilyGroupRefElement(child, ComplexReferenceParentType.Unknown, id); 6286 this.ParsePatchFamilyGroupRefElement(child, ComplexReferenceParentType.Unknown, id.Id);
6336 break; 6287 break;
6337 case "PayloadGroup": 6288 case "PayloadGroup":
6338 this.ParsePayloadGroupElement(child, ComplexReferenceParentType.Unknown, null); 6289 this.ParsePayloadGroupElement(child, ComplexReferenceParentType.Unknown, null);
@@ -6384,8 +6335,7 @@ namespace WixToolset.Core
6384 6335
6385 if (!this.Core.EncounteredError && null != id) 6336 if (!this.Core.EncounteredError && null != id)
6386 { 6337 {
6387 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixFragment); 6338 this.Core.AddTuple(new WixFragmentTuple(sourceLineNumbers, id));
6388 row.Set(0, id);
6389 } 6339 }
6390 } 6340 }
6391 6341
@@ -6498,11 +6448,13 @@ namespace WixToolset.Core
6498 6448
6499 if (!this.Core.EncounteredError) 6449 if (!this.Core.EncounteredError)
6500 { 6450 {
6501 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ControlCondition); 6451 this.Core.AddTuple(new ControlConditionTuple(sourceLineNumbers)
6502 row.Set(0, dialog); 6452 {
6503 row.Set(1, id); 6453 Dialog_ = dialog,
6504 row.Set(2, action); 6454 Control_ = id,
6505 row.Set(3, condition); 6455 Action = action,
6456 Condition = condition,
6457 });
6506 } 6458 }
6507 break; 6459 break;
6508 case "Feature": 6460 case "Feature":
@@ -6514,10 +6466,12 @@ namespace WixToolset.Core
6514 6466
6515 if (!this.Core.EncounteredError) 6467 if (!this.Core.EncounteredError)
6516 { 6468 {
6517 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Condition); 6469 this.Core.AddTuple(new ConditionTuple(sourceLineNumbers)
6518 row.Set(0, id); 6470 {
6519 row.Set(1, level); 6471 Feature_ = id,
6520 row.Set(2, condition); 6472 Level = level,
6473 Condition = condition
6474 });
6521 } 6475 }
6522 break; 6476 break;
6523 case "Fragment": 6477 case "Fragment":
@@ -6529,9 +6483,11 @@ namespace WixToolset.Core
6529 6483
6530 if (!this.Core.EncounteredError) 6484 if (!this.Core.EncounteredError)
6531 { 6485 {
6532 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.LaunchCondition); 6486 this.Core.AddTuple(new LaunchConditionTuple(sourceLineNumbers)
6533 row.Set(0, condition); 6487 {
6534 row.Set(1, message); 6488 Condition = condition,
6489 Description = message
6490 });
6535 } 6491 }
6536 break; 6492 break;
6537 } 6493 }
@@ -6836,7 +6792,7 @@ namespace WixToolset.Core
6836 } 6792 }
6837 oneChild = true; 6793 oneChild = true;
6838 signature = this.ParseFileSearchElement(child, id.Id, false, CompilerConstants.IntegerNotSet); 6794 signature = this.ParseFileSearchElement(child, id.Id, false, CompilerConstants.IntegerNotSet);
6839 id = new Identifier(signature, AccessModifier.Private); // FileSearch signatures override parent signatures 6795 id = new Identifier(AccessModifier.Private, signature); // FileSearch signatures override parent signatures
6840 break; 6796 break;
6841 case "FileSearchRef": 6797 case "FileSearchRef":
6842 if (oneChild) 6798 if (oneChild)
@@ -6845,7 +6801,7 @@ namespace WixToolset.Core
6845 } 6801 }
6846 oneChild = true; 6802 oneChild = true;
6847 var newId = this.ParseSimpleRefElement(child, "Signature"); // FileSearch signatures override parent signatures 6803 var newId = this.ParseSimpleRefElement(child, "Signature"); // FileSearch signatures override parent signatures
6848 id = new Identifier(newId, AccessModifier.Private); 6804 id = new Identifier(AccessModifier.Private, newId);
6849 signature = null; 6805 signature = null;
6850 break; 6806 break;
6851 default: 6807 default:
@@ -6861,15 +6817,20 @@ namespace WixToolset.Core
6861 6817
6862 if (!this.Core.EncounteredError) 6818 if (!this.Core.EncounteredError)
6863 { 6819 {
6864 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.IniLocator, id); 6820 var tuple = new IniLocatorTuple(sourceLineNumbers, id)
6865 row.Set(1, this.GetMsiFilenameValue(shortName, name)); 6821 {
6866 row.Set(2, section); 6822 FileName = this.GetMsiFilenameValue(shortName, name),
6867 row.Set(3, key); 6823 Section = section,
6824 Key = key,
6825 Type = type
6826 };
6827
6868 if (CompilerConstants.IntegerNotSet != field) 6828 if (CompilerConstants.IntegerNotSet != field)
6869 { 6829 {
6870 row.Set(4, field); 6830 tuple.Field = field;
6871 } 6831 }
6872 row.Set(5, type); 6832
6833 this.Core.AddTuple(tuple);
6873 } 6834 }
6874 6835
6875 return signature; 6836 return signature;
@@ -6915,9 +6876,11 @@ namespace WixToolset.Core
6915 6876
6916 if (!this.Core.EncounteredError) 6877 if (!this.Core.EncounteredError)
6917 { 6878 {
6918 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.IsolatedComponent); 6879 this.Core.AddTuple(new IsolatedComponentTuple(sourceLineNumbers)
6919 row.Set(0, shared); 6880 {
6920 row.Set(1, componentId); 6881 Component_Shared = shared,
6882 Component_Application = componentId
6883 });
6921 } 6884 }
6922 } 6885 }
6923 6886
@@ -6953,9 +6916,9 @@ namespace WixToolset.Core
6953 6916
6954 if (!this.Core.EncounteredError) 6917 if (!this.Core.EncounteredError)
6955 { 6918 {
6956 var row = this.Core.CreateRow(sourceLineNumbers, "PatchCertificates" == node.Name.LocalName ? TupleDefinitionType.MsiPatchCertificate : TupleDefinitionType.MsiPackageCertificate); 6919 var tuple = this.Core.CreateTuple(sourceLineNumbers, "PatchCertificates" == node.Name.LocalName ? TupleDefinitionType.MsiPatchCertificate : TupleDefinitionType.MsiPackageCertificate);
6957 row.Set(0, name); 6920 tuple.Set(0, name);
6958 row.Set(1, name); 6921 tuple.Set(1, name);
6959 } 6922 }
6960 break; 6923 break;
6961 default: 6924 default:
@@ -7026,8 +6989,10 @@ namespace WixToolset.Core
7026 6989
7027 if (!this.Core.EncounteredError) 6990 if (!this.Core.EncounteredError)
7028 { 6991 {
7029 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiDigitalCertificate, id); 6992 this.Core.AddTuple(new MsiDigitalCertificateTuple(sourceLineNumbers, id)
7030 row.Set(1, sourceFile); 6993 {
6994 CertData = sourceFile
6995 });
7031 } 6996 }
7032 6997
7033 return id.Id; 6998 return id.Id;
@@ -7097,11 +7062,13 @@ namespace WixToolset.Core
7097 7062
7098 if (!this.Core.EncounteredError) 7063 if (!this.Core.EncounteredError)
7099 { 7064 {
7100 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiDigitalSignature); 7065 this.Core.AddTuple(new MsiDigitalSignatureTuple(sourceLineNumbers, new Identifier(AccessModifier.Public, "Media", diskId))
7101 row.Set(0, "Media"); 7066 {
7102 row.Set(1, diskId); 7067 Table = "Media",
7103 row.Set(2, certificateId); 7068 SignObject = diskId,
7104 row.Set(3, sourceFile); 7069 DigitalCertificate_ = certificateId,
7070 Hash = sourceFile
7071 });
7105 } 7072 }
7106 } 7073 }
7107 7074
@@ -7242,7 +7209,7 @@ namespace WixToolset.Core
7242 this.Core.AddTuple(tuple); 7209 this.Core.AddTuple(tuple);
7243 7210
7244 // Ensure the action property is secure. 7211 // Ensure the action property is secure.
7245 this.AddWixPropertyRow(sourceLineNumbers, new Identifier(Common.UpgradeDetectedProperty, AccessModifier.Public), false, true, false); 7212 this.AddWixPropertyRow(sourceLineNumbers, new Identifier(AccessModifier.Public, Common.UpgradeDetectedProperty), false, true, false);
7246 7213
7247 // Add launch condition that blocks upgrades 7214 // Add launch condition that blocks upgrades
7248 if (blockUpgrades) 7215 if (blockUpgrades)
@@ -7273,7 +7240,7 @@ namespace WixToolset.Core
7273 this.Core.AddTuple(upgradeTuple); 7240 this.Core.AddTuple(upgradeTuple);
7274 7241
7275 // Ensure the action property is secure. 7242 // Ensure the action property is secure.
7276 this.AddWixPropertyRow(sourceLineNumbers, new Identifier(Common.DowngradeDetectedProperty, AccessModifier.Public), false, true, false); 7243 this.AddWixPropertyRow(sourceLineNumbers, new Identifier(AccessModifier.Public, Common.DowngradeDetectedProperty), false, true, false);
7277 7244
7278 var conditionTuple = new LaunchConditionTuple(sourceLineNumbers) 7245 var conditionTuple = new LaunchConditionTuple(sourceLineNumbers)
7279 { 7246 {
@@ -7479,29 +7446,27 @@ namespace WixToolset.Core
7479 // add the row to the section 7446 // add the row to the section
7480 if (!this.Core.EncounteredError) 7447 if (!this.Core.EncounteredError)
7481 { 7448 {
7482 var mediaRow = (MediaTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Media, new Identifier(id, AccessModifier.Public)); 7449 var tuple = new MediaTuple(sourceLineNumbers, new Identifier(AccessModifier.Public, id))
7483 mediaRow.LastSequence = 0; // this is set in the binder
7484 mediaRow.DiskPrompt = diskPrompt;
7485 mediaRow.Cabinet = cabinet;
7486 mediaRow.VolumeLabel = volumeLabel;
7487 mediaRow.Source = source;
7488
7489 // the Source column is only set when creating a patch
7490
7491 if (null != compressionLevel || null != layout)
7492 { 7450 {
7493 var row = (WixMediaTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixMedia); 7451 DiskId = id,
7494 row.DiskId_ = id; 7452 DiskPrompt = diskPrompt,
7495 row.CompressionLevel = compressionLevel; 7453 Cabinet = cabinet,
7496 row.Layout = layout; 7454 VolumeLabel = volumeLabel,
7497 } 7455 Source = source, // the Source column is only set when creating a patch
7456 CompressionLevel = compressionLevel,
7457 Layout = layout
7458 };
7459
7460 this.Core.AddTuple(tuple);
7498 7461
7499 if (null != symbols) 7462 if (null != symbols)
7500 { 7463 {
7501 var symbolRow = (WixDeltaPatchSymbolPathsTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixDeltaPatchSymbolPaths); 7464 this.Core.AddTuple(new WixDeltaPatchSymbolPathsTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, SymbolPathType.Media, id))
7502 symbolRow.Id = id.ToString(CultureInfo.InvariantCulture); 7465 {
7503 symbolRow.Type = SymbolPathType.Media; 7466 SymbolType = SymbolPathType.Media,
7504 symbolRow.SymbolPaths = symbols; 7467 SymbolId = id.ToString(CultureInfo.InvariantCulture),
7468 SymbolPaths = symbols
7469 });
7505 } 7470 }
7506 } 7471 }
7507 } 7472 }
@@ -7518,8 +7483,8 @@ namespace WixToolset.Core
7518 string diskPrompt = null; 7483 string diskPrompt = null;
7519 var patch = null != patchId; 7484 var patch = null != patchId;
7520 string volumeLabel = null; 7485 string volumeLabel = null;
7521 var maximumUncompressedMediaSize = CompilerConstants.IntegerNotSet; 7486 int? maximumUncompressedMediaSize = null;
7522 var maximumCabinetSizeForLargeFileSplitting = CompilerConstants.IntegerNotSet; 7487 int? maximumCabinetSizeForLargeFileSplitting = null;
7523 CompressionLevel? compressionLevel = null; // this defaults to mszip in Binder 7488 CompressionLevel? compressionLevel = null; // this defaults to mszip in Binder
7524 7489
7525 var embedCab = patch ? YesNoType.Yes : YesNoType.NotSet; 7490 var embedCab = patch ? YesNoType.Yes : YesNoType.NotSet;
@@ -7572,7 +7537,7 @@ namespace WixToolset.Core
7572 maximumUncompressedMediaSize = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, Int32.MaxValue); 7537 maximumUncompressedMediaSize = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, Int32.MaxValue);
7573 break; 7538 break;
7574 case "MaximumCabinetSizeForLargeFileSplitting": 7539 case "MaximumCabinetSizeForLargeFileSplitting":
7575 maximumCabinetSizeForLargeFileSplitting = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, CompilerCore.MinValueOfMaxCabSizeForLargeFileSplitting, CompilerCore.MaxValueOfMaxCabSizeForLargeFileSplitting); 7540 maximumCabinetSizeForLargeFileSplitting = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, Compiler.MinValueOfMaxCabSizeForLargeFileSplitting, Compiler.MaxValueOfMaxCabSizeForLargeFileSplitting);
7576 break; 7541 break;
7577 default: 7542 default:
7578 this.Core.UnexpectedAttribute(node, attrib); 7543 this.Core.UnexpectedAttribute(node, attrib);
@@ -7585,46 +7550,39 @@ namespace WixToolset.Core
7585 } 7550 }
7586 } 7551 }
7587 7552
7588 if (YesNoType.IllegalValue != embedCab) 7553 if (YesNoType.Yes == embedCab)
7589 { 7554 {
7590 if (YesNoType.Yes == embedCab) 7555 cabinetTemplate = String.Concat("#", cabinetTemplate);
7591 {
7592 cabinetTemplate = String.Concat("#", cabinetTemplate);
7593 }
7594 } 7556 }
7595 7557
7596 if (!this.Core.EncounteredError) 7558 if (!this.Core.EncounteredError)
7597 { 7559 {
7598 var temporaryMediaRow = (MediaTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Media, new Identifier(1, AccessModifier.Public)); 7560 this.Core.AddTuple(new MediaTuple(sourceLineNumbers, new Identifier(AccessModifier.Public, 1))
7599
7600 var mediaTemplateRow = (WixMediaTemplateTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixMediaTemplate);
7601 mediaTemplateRow.CabinetTemplate = cabinetTemplate;
7602 mediaTemplateRow.VolumeLabel = volumeLabel;
7603 mediaTemplateRow.DiskPrompt = diskPrompt;
7604 mediaTemplateRow.VolumeLabel = volumeLabel;
7605
7606 if (maximumUncompressedMediaSize != CompilerConstants.IntegerNotSet)
7607 { 7561 {
7608 mediaTemplateRow.MaximumUncompressedMediaSize = maximumUncompressedMediaSize; 7562 DiskId = 1
7609 } 7563 });
7610 else
7611 {
7612 mediaTemplateRow.MaximumUncompressedMediaSize = CompilerCore.DefaultMaximumUncompressedMediaSize;
7613 }
7614 7564
7615 if (maximumCabinetSizeForLargeFileSplitting != CompilerConstants.IntegerNotSet) 7565 var tuple = new WixMediaTemplateTuple(sourceLineNumbers)
7616 {
7617 mediaTemplateRow.MaximumCabinetSizeForLargeFileSplitting = maximumCabinetSizeForLargeFileSplitting;
7618 }
7619 else
7620 { 7566 {
7621 mediaTemplateRow.MaximumCabinetSizeForLargeFileSplitting = 0; // Default value of 0 corresponds to max size of 2048 MB (i.e. 2 GB) 7567 CabinetTemplate = cabinetTemplate,
7622 } 7568 VolumeLabel = volumeLabel,
7569 DiskPrompt = diskPrompt,
7570 MaximumUncompressedMediaSize = maximumUncompressedMediaSize,
7571 MaximumCabinetSizeForLargeFileSplitting = maximumCabinetSizeForLargeFileSplitting,
7572 CompressionLevel = compressionLevel
7573 };
7623 7574
7624 if (compressionLevel.HasValue) 7575 //else
7625 { 7576 //{
7626 mediaTemplateRow.CompressionLevel = compressionLevel.Value; 7577 // mediaTemplateRow.MaximumUncompressedMediaSize = CompilerCore.DefaultMaximumUncompressedMediaSize;
7627 } 7578 //}
7579
7580 //else
7581 //{
7582 // mediaTemplateRow.MaximumCabinetSizeForLargeFileSplitting = 0; // Default value of 0 corresponds to max size of 2048 MB (i.e. 2 GB)
7583 //}
7584
7585 this.Core.AddTuple(tuple);
7628 } 7586 }
7629 } 7587 }
7630 7588
@@ -7639,7 +7597,7 @@ namespace WixToolset.Core
7639 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); 7597 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
7640 Identifier id = null; 7598 Identifier id = null;
7641 var configData = String.Empty; 7599 var configData = String.Empty;
7642 var fileCompression = YesNoType.NotSet; 7600 bool? fileCompression = null;
7643 string language = null; 7601 string language = null;
7644 string sourceFile = null; 7602 string sourceFile = null;
7645 7603
@@ -7657,7 +7615,7 @@ namespace WixToolset.Core
7657 this.Core.CreateSimpleReference(sourceLineNumbers, "Media", diskId.ToString(CultureInfo.InvariantCulture.NumberFormat)); 7615 this.Core.CreateSimpleReference(sourceLineNumbers, "Media", diskId.ToString(CultureInfo.InvariantCulture.NumberFormat));
7658 break; 7616 break;
7659 case "FileCompression": 7617 case "FileCompression":
7660 fileCompression = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib); 7618 fileCompression = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
7661 break; 7619 break;
7662 case "Language": 7620 case "Language":
7663 language = this.Core.GetAttributeLocalizableIntegerValue(sourceLineNumbers, attrib, 0, Int16.MaxValue); 7621 language = this.Core.GetAttributeLocalizableIntegerValue(sourceLineNumbers, attrib, 0, Int16.MaxValue);
@@ -7726,25 +7684,19 @@ namespace WixToolset.Core
7726 7684
7727 if (!this.Core.EncounteredError) 7685 if (!this.Core.EncounteredError)
7728 { 7686 {
7729 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixMerge, id); 7687 var tuple = new WixMergeTuple(sourceLineNumbers, id)
7730 row.Set(1, language);
7731 row.Set(2, directoryId);
7732 row.Set(3, sourceFile);
7733 row.Set(4, diskId);
7734 if (YesNoType.Yes == fileCompression)
7735 {
7736 row.Set(5, true);
7737 }
7738 else if (YesNoType.No == fileCompression)
7739 { 7688 {
7740 row.Set(5, false); 7689 Directory_ = directoryId,
7741 } 7690 SourceFile = sourceFile,
7742 else // YesNoType.NotSet == fileCompression 7691 DiskId = diskId,
7743 { 7692 ConfigurationData = configData,
7744 // and we leave the column null 7693 FileCompression = fileCompression,
7745 } 7694 Feature_ = Guid.Empty.ToString("B")
7746 row.Set(6, configData); 7695 };
7747 row.Set(7, Guid.Empty.ToString("B")); 7696
7697 tuple.Set((int)WixMergeTupleFields.Language, language);
7698
7699 this.Core.AddTuple(tuple);
7748 } 7700 }
7749 } 7701 }
7750 7702
@@ -7922,10 +7874,14 @@ namespace WixToolset.Core
7922 7874
7923 if (!this.Core.EncounteredError) 7875 if (!this.Core.EncounteredError)
7924 { 7876 {
7925 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MIME); 7877 var tuple = new MIMETuple(sourceLineNumbers, new Identifier(AccessModifier.Private, contentType))
7926 row.Set(0, contentType); 7878 {
7927 row.Set(1, extension); 7879 ContentType = contentType,
7928 row.Set(2, classId); 7880 Extension_ = extension,
7881 CLSID = classId
7882 };
7883
7884 this.Core.AddTuple(tuple);
7929 } 7885 }
7930 } 7886 }
7931 else if (YesNoType.No == advertise) 7887 else if (YesNoType.No == advertise)
@@ -7946,935 +7902,6 @@ namespace WixToolset.Core
7946 } 7902 }
7947 7903
7948 /// <summary> 7904 /// <summary>
7949 /// Parses a patch creation element.
7950 /// </summary>
7951 /// <param name="node">The element to parse.</param>
7952 private void ParsePatchCreationElement(XElement node)
7953 {
7954 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
7955 var clean = true; // Default is to clean
7956 var codepage = 0;
7957 string outputPath = null;
7958 var productMismatches = false;
7959 var replaceGuids = String.Empty;
7960 string sourceList = null;
7961 string symbolFlags = null;
7962 var targetProducts = String.Empty;
7963 var versionMismatches = false;
7964 var wholeFiles = false;
7965
7966 foreach (var attrib in node.Attributes())
7967 {
7968 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
7969 {
7970 switch (attrib.Name.LocalName)
7971 {
7972 case "Id":
7973 this.activeName = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false);
7974 break;
7975 case "AllowMajorVersionMismatches":
7976 versionMismatches = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
7977 break;
7978 case "AllowProductCodeMismatches":
7979 productMismatches = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
7980 break;
7981 case "CleanWorkingFolder":
7982 clean = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
7983 break;
7984 case "Codepage":
7985 codepage = this.Core.GetAttributeCodePageValue(sourceLineNumbers, attrib);
7986 break;
7987 case "OutputPath":
7988 outputPath = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
7989 break;
7990 case "SourceList":
7991 sourceList = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
7992 break;
7993 case "SymbolFlags":
7994 symbolFlags = String.Format(CultureInfo.InvariantCulture, "0x{0:x8}", this.Core.GetAttributeLongValue(sourceLineNumbers, attrib, 0, UInt32.MaxValue));
7995 break;
7996 case "WholeFilesOnly":
7997 wholeFiles = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
7998 break;
7999 default:
8000 this.Core.UnexpectedAttribute(node, attrib);
8001 break;
8002 }
8003 }
8004 else
8005 {
8006 this.Core.ParseExtensionAttribute(node, attrib);
8007 }
8008 }
8009
8010 if (null == this.activeName)
8011 {
8012 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
8013 }
8014
8015 this.Core.CreateActiveSection(this.activeName, SectionType.PatchCreation, codepage, this.Context.CompilationId);
8016
8017 foreach (var child in node.Elements())
8018 {
8019 if (CompilerCore.WixNamespace == child.Name.Namespace)
8020 {
8021 switch (child.Name.LocalName)
8022 {
8023 case "Family":
8024 this.ParseFamilyElement(child);
8025 break;
8026 case "PatchInformation":
8027 this.ParsePatchInformationElement(child);
8028 break;
8029 case "PatchMetadata":
8030 this.ParsePatchMetadataElement(child);
8031 break;
8032 case "PatchProperty":
8033 this.ParsePatchPropertyElement(child, false);
8034 break;
8035 case "PatchSequence":
8036 this.ParsePatchSequenceElement(child);
8037 break;
8038 case "ReplacePatch":
8039 replaceGuids = String.Concat(replaceGuids, this.ParseReplacePatchElement(child));
8040 break;
8041 case "TargetProductCode":
8042 var targetProduct = this.ParseTargetProductCodeElement(child);
8043 if (0 < targetProducts.Length)
8044 {
8045 targetProducts = String.Concat(targetProducts, ";");
8046 }
8047 targetProducts = String.Concat(targetProducts, targetProduct);
8048 break;
8049 default:
8050 this.Core.UnexpectedElement(node, child);
8051 break;
8052 }
8053 }
8054 else
8055 {
8056 this.Core.ParseExtensionElement(node, child);
8057 }
8058 }
8059
8060 this.ProcessProperties(sourceLineNumbers, "PatchGUID", this.activeName);
8061 this.ProcessProperties(sourceLineNumbers, "AllowProductCodeMismatches", productMismatches ? "1" : "0");
8062 this.ProcessProperties(sourceLineNumbers, "AllowProductVersionMajorMismatches", versionMismatches ? "1" : "0");
8063 this.ProcessProperties(sourceLineNumbers, "DontRemoveTempFolderWhenFinished", clean ? "0" : "1");
8064 this.ProcessProperties(sourceLineNumbers, "IncludeWholeFilesOnly", wholeFiles ? "1" : "0");
8065
8066 if (null != symbolFlags)
8067 {
8068 this.ProcessProperties(sourceLineNumbers, "ApiPatchingSymbolFlags", symbolFlags);
8069 }
8070
8071 if (0 < replaceGuids.Length)
8072 {
8073 this.ProcessProperties(sourceLineNumbers, "ListOfPatchGUIDsToReplace", replaceGuids);
8074 }
8075
8076 if (0 < targetProducts.Length)
8077 {
8078 this.ProcessProperties(sourceLineNumbers, "ListOfTargetProductCodes", targetProducts);
8079 }
8080
8081 if (null != outputPath)
8082 {
8083 this.ProcessProperties(sourceLineNumbers, "PatchOutputPath", outputPath);
8084 }
8085
8086 if (null != sourceList)
8087 {
8088 this.ProcessProperties(sourceLineNumbers, "PatchSourceList", sourceList);
8089 }
8090 }
8091
8092 /// <summary>
8093 /// Parses a family element.
8094 /// </summary>
8095 /// <param name="node">The element to parse.</param>
8096 private void ParseFamilyElement(XElement node)
8097 {
8098 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
8099 var diskId = CompilerConstants.IntegerNotSet;
8100 string diskPrompt = null;
8101 string mediaSrcProp = null;
8102 string name = null;
8103 var sequenceStart = CompilerConstants.IntegerNotSet;
8104 string volumeLabel = null;
8105
8106 foreach (var attrib in node.Attributes())
8107 {
8108 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
8109 {
8110 switch (attrib.Name.LocalName)
8111 {
8112 case "DiskId":
8113 diskId = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, Int16.MaxValue);
8114 break;
8115 case "DiskPrompt":
8116 diskPrompt = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
8117 break;
8118 case "MediaSrcProp":
8119 mediaSrcProp = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
8120 break;
8121 case "Name":
8122 name = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
8123 break;
8124 case "SequenceStart":
8125 sequenceStart = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, Int32.MaxValue);
8126 break;
8127 case "VolumeLabel":
8128 volumeLabel = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
8129 break;
8130 default:
8131 this.Core.UnexpectedAttribute(node, attrib);
8132 break;
8133 }
8134 }
8135 else
8136 {
8137 this.Core.ParseExtensionAttribute(node, attrib);
8138 }
8139 }
8140
8141 if (null == name)
8142 {
8143 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Name"));
8144 }
8145 else if (0 < name.Length)
8146 {
8147 if (8 < name.Length) // check the length
8148 {
8149 this.Core.Write(ErrorMessages.FamilyNameTooLong(sourceLineNumbers, node.Name.LocalName, "Name", name, name.Length));
8150 }
8151 else // check for illegal characters
8152 {
8153 foreach (var character in name)
8154 {
8155 if (!Char.IsLetterOrDigit(character) && '_' != character)
8156 {
8157 this.Core.Write(ErrorMessages.IllegalFamilyName(sourceLineNumbers, node.Name.LocalName, "Name", name));
8158 }
8159 }
8160 }
8161 }
8162
8163 foreach (var child in node.Elements())
8164 {
8165 if (CompilerCore.WixNamespace == child.Name.Namespace)
8166 {
8167 switch (child.Name.LocalName)
8168 {
8169 case "UpgradeImage":
8170 this.ParseUpgradeImageElement(child, name);
8171 break;
8172 case "ExternalFile":
8173 this.ParseExternalFileElement(child, name);
8174 break;
8175 case "ProtectFile":
8176 this.ParseProtectFileElement(child, name);
8177 break;
8178 default:
8179 this.Core.UnexpectedElement(node, child);
8180 break;
8181 }
8182 }
8183 else
8184 {
8185 this.Core.ParseExtensionElement(node, child);
8186 }
8187 }
8188
8189 if (!this.Core.EncounteredError)
8190 {
8191 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ImageFamilies);
8192 row.Set(0, name);
8193 row.Set(1, mediaSrcProp);
8194 if (CompilerConstants.IntegerNotSet != diskId)
8195 {
8196 row.Set(2, diskId);
8197 }
8198
8199 if (CompilerConstants.IntegerNotSet != sequenceStart)
8200 {
8201 row.Set(3, sequenceStart);
8202 }
8203 row.Set(4, diskPrompt);
8204 row.Set(5, volumeLabel);
8205 }
8206 }
8207
8208 /// <summary>
8209 /// Parses an upgrade image element.
8210 /// </summary>
8211 /// <param name="node">The element to parse.</param>
8212 /// <param name="family">The family for this element.</param>
8213 private void ParseUpgradeImageElement(XElement node, string family)
8214 {
8215 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
8216 string sourceFile = null;
8217 string sourcePatch = null;
8218 var symbols = new List<string>();
8219 string upgrade = null;
8220
8221 foreach (var attrib in node.Attributes())
8222 {
8223 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
8224 {
8225 switch (attrib.Name.LocalName)
8226 {
8227 case "Id":
8228 upgrade = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
8229 if (13 < upgrade.Length)
8230 {
8231 this.Core.Write(ErrorMessages.IdentifierTooLongError(sourceLineNumbers, node.Name.LocalName, "Id", upgrade, 13));
8232 }
8233 break;
8234 case "SourceFile":
8235 case "src":
8236 if (null != sourceFile)
8237 {
8238 this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, "src", "SourceFile"));
8239 }
8240
8241 if ("src" == attrib.Name.LocalName)
8242 {
8243 this.Core.Write(WarningMessages.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "SourceFile"));
8244 }
8245 sourceFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
8246 break;
8247 case "SourcePatch":
8248 case "srcPatch":
8249 if (null != sourcePatch)
8250 {
8251 this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, "srcPatch", "SourcePatch"));
8252 }
8253
8254 if ("srcPatch" == attrib.Name.LocalName)
8255 {
8256 this.Core.Write(WarningMessages.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "SourcePatch"));
8257 }
8258 sourcePatch = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
8259 break;
8260 default:
8261 this.Core.UnexpectedAttribute(node, attrib);
8262 break;
8263 }
8264 }
8265 else
8266 {
8267 this.Core.ParseExtensionAttribute(node, attrib);
8268 }
8269 }
8270
8271 if (null == upgrade)
8272 {
8273 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
8274 }
8275
8276 if (null == sourceFile)
8277 {
8278 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "SourceFile"));
8279 }
8280
8281 foreach (var child in node.Elements())
8282 {
8283 if (CompilerCore.WixNamespace == child.Name.Namespace)
8284 {
8285 switch (child.Name.LocalName)
8286 {
8287 case "SymbolPath":
8288 symbols.Add(this.ParseSymbolPathElement(child));
8289 break;
8290 case "TargetImage":
8291 this.ParseTargetImageElement(child, upgrade, family);
8292 break;
8293 case "UpgradeFile":
8294 this.ParseUpgradeFileElement(child, upgrade);
8295 break;
8296 default:
8297 this.Core.UnexpectedElement(node, child);
8298 break;
8299 }
8300 }
8301 else
8302 {
8303 this.Core.ParseExtensionElement(node, child);
8304 }
8305 }
8306
8307 if (!this.Core.EncounteredError)
8308 {
8309 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.UpgradedImages);
8310 row.Set(0, upgrade);
8311 row.Set(1, sourceFile);
8312 row.Set(2, sourcePatch);
8313 row.Set(3, String.Join(";", symbols));
8314 row.Set(4, family);
8315 }
8316 }
8317
8318 /// <summary>
8319 /// Parses an upgrade file element.
8320 /// </summary>
8321 /// <param name="node">The element to parse.</param>
8322 /// <param name="upgrade">The upgrade key for this element.</param>
8323 private void ParseUpgradeFileElement(XElement node, string upgrade)
8324 {
8325 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
8326 var allowIgnoreOnError = false;
8327 string file = null;
8328 var ignore = false;
8329 var symbols = new List<string>();
8330 var wholeFile = false;
8331
8332 foreach (var attrib in node.Attributes())
8333 {
8334 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
8335 {
8336 switch (attrib.Name.LocalName)
8337 {
8338 case "AllowIgnoreOnError":
8339 allowIgnoreOnError = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
8340 break;
8341 case "File":
8342 file = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
8343 break;
8344 case "Ignore":
8345 ignore = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
8346 break;
8347 case "WholeFile":
8348 wholeFile = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
8349 break;
8350 default:
8351 this.Core.UnexpectedAttribute(node, attrib);
8352 break;
8353 }
8354 }
8355 else
8356 {
8357 this.Core.ParseExtensionAttribute(node, attrib);
8358 }
8359 }
8360
8361 if (null == file)
8362 {
8363 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "File"));
8364 }
8365
8366 foreach (var child in node.Elements())
8367 {
8368 if (CompilerCore.WixNamespace == child.Name.Namespace)
8369 {
8370 switch (child.Name.LocalName)
8371 {
8372 case "SymbolPath":
8373 symbols.Add(this.ParseSymbolPathElement(child));
8374 break;
8375 default:
8376 this.Core.UnexpectedElement(node, child);
8377 break;
8378 }
8379 }
8380 else
8381 {
8382 this.Core.ParseExtensionElement(node, child);
8383 }
8384 }
8385
8386 if (!this.Core.EncounteredError)
8387 {
8388 if (ignore)
8389 {
8390 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.UpgradedFilesToIgnore);
8391 row.Set(0, upgrade);
8392 row.Set(1, file);
8393 }
8394 else
8395 {
8396 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.UpgradedFiles_OptionalData);
8397 row.Set(0, upgrade);
8398 row.Set(1, file);
8399 row.Set(2, String.Join(";", symbols));
8400 row.Set(3, allowIgnoreOnError ? 1 : 0);
8401 row.Set(4, wholeFile ? 1 : 0);
8402 }
8403 }
8404 }
8405
8406 /// <summary>
8407 /// Parses a target image element.
8408 /// </summary>
8409 /// <param name="node">The element to parse.</param>
8410 /// <param name="upgrade">The upgrade key for this element.</param>
8411 /// <param name="family">The family key for this element.</param>
8412 private void ParseTargetImageElement(XElement node, string upgrade, string family)
8413 {
8414 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
8415 var ignore = false;
8416 var order = CompilerConstants.IntegerNotSet;
8417 string sourceFile = null;
8418 string symbols = null;
8419 string target = null;
8420 string validation = null;
8421
8422 foreach (var attrib in node.Attributes())
8423 {
8424 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
8425 {
8426 switch (attrib.Name.LocalName)
8427 {
8428 case "Id":
8429 target = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
8430 if (target.Length > 13)
8431 {
8432 this.Core.Write(ErrorMessages.IdentifierTooLongError(sourceLineNumbers, node.Name.LocalName, "Id", target, 13));
8433 }
8434 break;
8435 case "IgnoreMissingFiles":
8436 ignore = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
8437 break;
8438 case "Order":
8439 order = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, Int32.MinValue + 2, Int32.MaxValue);
8440 break;
8441 case "SourceFile":
8442 case "src":
8443 if (null != sourceFile)
8444 {
8445 this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, "src", "SourceFile"));
8446 }
8447
8448 if ("src" == attrib.Name.LocalName)
8449 {
8450 this.Core.Write(WarningMessages.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "SourceFile"));
8451 }
8452 sourceFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
8453 break;
8454 case "Validation":
8455 validation = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
8456 break;
8457 default:
8458 this.Core.UnexpectedAttribute(node, attrib);
8459 break;
8460 }
8461 }
8462 else
8463 {
8464 this.Core.ParseExtensionAttribute(node, attrib);
8465 }
8466 }
8467
8468 if (null == target)
8469 {
8470 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
8471 }
8472
8473 if (null == sourceFile)
8474 {
8475 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "SourceFile"));
8476 }
8477
8478 if (CompilerConstants.IntegerNotSet == order)
8479 {
8480 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Order"));
8481 }
8482
8483 foreach (var child in node.Elements())
8484 {
8485 if (CompilerCore.WixNamespace == child.Name.Namespace)
8486 {
8487 switch (child.Name.LocalName)
8488 {
8489 case "SymbolPath":
8490 if (null != symbols)
8491 {
8492 symbols = String.Concat(symbols, ";", this.ParseSymbolPathElement(child));
8493 }
8494 else
8495 {
8496 symbols = this.ParseSymbolPathElement(child);
8497 }
8498 break;
8499 case "TargetFile":
8500 this.ParseTargetFileElement(child, target, family);
8501 break;
8502 default:
8503 this.Core.UnexpectedElement(node, child);
8504 break;
8505 }
8506 }
8507 else
8508 {
8509 this.Core.ParseExtensionElement(node, child);
8510 }
8511 }
8512
8513 if (!this.Core.EncounteredError)
8514 {
8515 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.TargetImages);
8516 row.Set(0, target);
8517 row.Set(1, sourceFile);
8518 row.Set(2, symbols);
8519 row.Set(3, upgrade);
8520 row.Set(4, order);
8521 row.Set(5, validation);
8522 row.Set(6, ignore ? 1 : 0);
8523 }
8524 }
8525
8526 /// <summary>
8527 /// Parses an upgrade file element.
8528 /// </summary>
8529 /// <param name="node">The element to parse.</param>
8530 /// <param name="target">The upgrade key for this element.</param>
8531 /// <param name="family">The family key for this element.</param>
8532 private void ParseTargetFileElement(XElement node, string target, string family)
8533 {
8534 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
8535 string file = null;
8536 string ignoreLengths = null;
8537 string ignoreOffsets = null;
8538 string protectLengths = null;
8539 string protectOffsets = null;
8540 string symbols = null;
8541
8542 foreach (var attrib in node.Attributes())
8543 {
8544 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
8545 {
8546 switch (attrib.Name.LocalName)
8547 {
8548 case "Id":
8549 file = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
8550 break;
8551 default:
8552 this.Core.UnexpectedAttribute(node, attrib);
8553 break;
8554 }
8555 }
8556 else
8557 {
8558 this.Core.ParseExtensionAttribute(node, attrib);
8559 }
8560 }
8561
8562 if (null == file)
8563 {
8564 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
8565 }
8566
8567 foreach (var child in node.Elements())
8568 {
8569 if (CompilerCore.WixNamespace == child.Name.Namespace)
8570 {
8571 switch (child.Name.LocalName)
8572 {
8573 case "IgnoreRange":
8574 this.ParseRangeElement(child, ref ignoreOffsets, ref ignoreLengths);
8575 break;
8576 case "ProtectRange":
8577 this.ParseRangeElement(child, ref protectOffsets, ref protectLengths);
8578 break;
8579 case "SymbolPath":
8580 symbols = this.ParseSymbolPathElement(child);
8581 break;
8582 default:
8583 this.Core.UnexpectedElement(node, child);
8584 break;
8585 }
8586 }
8587 else
8588 {
8589 this.Core.ParseExtensionElement(node, child);
8590 }
8591 }
8592
8593 if (!this.Core.EncounteredError)
8594 {
8595 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.TargetFiles_OptionalData);
8596 row.Set(0, target);
8597 row.Set(1, file);
8598 row.Set(2, symbols);
8599 row.Set(3, ignoreOffsets);
8600 row.Set(4, ignoreLengths);
8601
8602 if (null != protectOffsets)
8603 {
8604 row.Set(5, protectOffsets);
8605
8606 var row2 = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.FamilyFileRanges);
8607 row2.Set(0, family);
8608 row2.Set(1, file);
8609 row2.Set(2, protectOffsets);
8610 row2.Set(3, protectLengths);
8611 }
8612 }
8613 }
8614
8615 /// <summary>
8616 /// Parses an external file element.
8617 /// </summary>
8618 /// <param name="node">The element to parse.</param>
8619 /// <param name="family">The family for this element.</param>
8620 private void ParseExternalFileElement(XElement node, string family)
8621 {
8622 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
8623 string file = null;
8624 string ignoreLengths = null;
8625 string ignoreOffsets = null;
8626 var order = CompilerConstants.IntegerNotSet;
8627 string protectLengths = null;
8628 string protectOffsets = null;
8629 string source = null;
8630 string symbols = null;
8631
8632 foreach (var attrib in node.Attributes())
8633 {
8634 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
8635 {
8636 switch (attrib.Name.LocalName)
8637 {
8638 case "File":
8639 file = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
8640 break;
8641 case "Order":
8642 order = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, Int32.MinValue + 2, Int32.MaxValue);
8643 break;
8644 case "Source":
8645 case "src":
8646 if (null != source)
8647 {
8648 this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, "src", "Source"));
8649 }
8650
8651 if ("src" == attrib.Name.LocalName)
8652 {
8653 this.Core.Write(WarningMessages.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "Source"));
8654 }
8655 source = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
8656 break;
8657 default:
8658 this.Core.UnexpectedAttribute(node, attrib);
8659 break;
8660 }
8661 }
8662 else
8663 {
8664 this.Core.ParseExtensionAttribute(node, attrib);
8665 }
8666 }
8667
8668 if (null == file)
8669 {
8670 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "File"));
8671 }
8672
8673 if (null == source)
8674 {
8675 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Source"));
8676 }
8677
8678 if (CompilerConstants.IntegerNotSet == order)
8679 {
8680 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Order"));
8681 }
8682
8683 foreach (var child in node.Elements())
8684 {
8685 if (CompilerCore.WixNamespace == child.Name.Namespace)
8686 {
8687 switch (child.Name.LocalName)
8688 {
8689 case "IgnoreRange":
8690 this.ParseRangeElement(child, ref ignoreOffsets, ref ignoreLengths);
8691 break;
8692 case "ProtectRange":
8693 this.ParseRangeElement(child, ref protectOffsets, ref protectLengths);
8694 break;
8695 case "SymbolPath":
8696 symbols = this.ParseSymbolPathElement(child);
8697 break;
8698 default:
8699 this.Core.UnexpectedElement(node, child);
8700 break;
8701 }
8702 }
8703 else
8704 {
8705 this.Core.ParseExtensionElement(node, child);
8706 }
8707 }
8708
8709 if (!this.Core.EncounteredError)
8710 {
8711 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ExternalFiles);
8712 row.Set(0, family);
8713 row.Set(1, file);
8714 row.Set(2, source);
8715 row.Set(3, symbols);
8716 row.Set(4, ignoreOffsets);
8717 row.Set(5, ignoreLengths);
8718 if (null != protectOffsets)
8719 {
8720 row.Set(6, protectOffsets);
8721 }
8722
8723 if (CompilerConstants.IntegerNotSet != order)
8724 {
8725 row.Set(7, order);
8726 }
8727
8728 if (null != protectOffsets)
8729 {
8730 var row2 = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.FamilyFileRanges);
8731 row2.Set(0, family);
8732 row2.Set(1, file);
8733 row2.Set(2, protectOffsets);
8734 row2.Set(3, protectLengths);
8735 }
8736 }
8737 }
8738
8739 /// <summary>
8740 /// Parses a protect file element.
8741 /// </summary>
8742 /// <param name="node">The element to parse.</param>
8743 /// <param name="family">The family for this element.</param>
8744 private void ParseProtectFileElement(XElement node, string family)
8745 {
8746 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
8747 string file = null;
8748 string protectLengths = null;
8749 string protectOffsets = null;
8750
8751 foreach (var attrib in node.Attributes())
8752 {
8753 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
8754 {
8755 switch (attrib.Name.LocalName)
8756 {
8757 case "File":
8758 file = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
8759 break;
8760 default:
8761 this.Core.UnexpectedAttribute(node, attrib);
8762 break;
8763 }
8764 }
8765 else
8766 {
8767 this.Core.ParseExtensionAttribute(node, attrib);
8768 }
8769 }
8770
8771 if (null == file)
8772 {
8773 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "File"));
8774 }
8775
8776 foreach (var child in node.Elements())
8777 {
8778 if (CompilerCore.WixNamespace == child.Name.Namespace)
8779 {
8780 switch (child.Name.LocalName)
8781 {
8782 case "ProtectRange":
8783 this.ParseRangeElement(child, ref protectOffsets, ref protectLengths);
8784 break;
8785 default:
8786 this.Core.UnexpectedElement(node, child);
8787 break;
8788 }
8789 }
8790 else
8791 {
8792 this.Core.ParseExtensionElement(node, child);
8793 }
8794 }
8795
8796 if (null == protectOffsets || null == protectLengths)
8797 {
8798 this.Core.Write(ErrorMessages.ExpectedElement(sourceLineNumbers, node.Name.LocalName, "ProtectRange"));
8799 }
8800
8801 if (!this.Core.EncounteredError)
8802 {
8803 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.FamilyFileRanges);
8804 row.Set(0, family);
8805 row.Set(1, file);
8806 row.Set(2, protectOffsets);
8807 row.Set(3, protectLengths);
8808 }
8809 }
8810
8811 /// <summary>
8812 /// Parses a range element (ProtectRange, IgnoreRange, etc).
8813 /// </summary>
8814 /// <param name="node">The element to parse.</param>
8815 /// <param name="offsets">Reference to the offsets string.</param>
8816 /// <param name="lengths">Reference to the lengths string.</param>
8817 private void ParseRangeElement(XElement node, ref string offsets, ref string lengths)
8818 {
8819 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
8820 string length = null;
8821 string offset = null;
8822
8823 foreach (var attrib in node.Attributes())
8824 {
8825 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
8826 {
8827 switch (attrib.Name.LocalName)
8828 {
8829 case "Length":
8830 length = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
8831 break;
8832 case "Offset":
8833 offset = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
8834 break;
8835 default:
8836 this.Core.UnexpectedAttribute(node, attrib);
8837 break;
8838 }
8839 }
8840 else
8841 {
8842 this.Core.ParseExtensionAttribute(node, attrib);
8843 }
8844 }
8845
8846 if (null == length)
8847 {
8848 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Length"));
8849 }
8850
8851 if (null == offset)
8852 {
8853 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Offset"));
8854 }
8855
8856 this.Core.ParseForExtensionElements(node);
8857
8858 if (null != lengths)
8859 {
8860 lengths = String.Concat(lengths, ",", length);
8861 }
8862 else
8863 {
8864 lengths = length;
8865 }
8866
8867 if (null != offsets)
8868 {
8869 offsets = String.Concat(offsets, ",", offset);
8870 }
8871 else
8872 {
8873 offsets = offset;
8874 }
8875 }
8876
8877 /// <summary>
8878 /// Parses a patch property element. 7905 /// Parses a patch property element.
8879 /// </summary> 7906 /// </summary>
8880 /// <param name="node">The element to parse.</param> 7907 /// <param name="node">The element to parse.</param>
@@ -8928,10 +7955,12 @@ namespace WixToolset.Core
8928 if (patch) 7955 if (patch)
8929 { 7956 {
8930 // /Patch/PatchProperty goes directly into MsiPatchMetadata table 7957 // /Patch/PatchProperty goes directly into MsiPatchMetadata table
8931 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiPatchMetadata); 7958 this.Core.AddTuple(new MsiPatchMetadataTuple(sourceLineNumbers)
8932 row.Set(0, company); 7959 {
8933 row.Set(1, name); 7960 Company = company,
8934 row.Set(2, value); 7961 Property = name,
7962 Value = value
7963 });
8935 } 7964 }
8936 else 7965 else
8937 { 7966 {
@@ -8939,91 +7968,26 @@ namespace WixToolset.Core
8939 { 7968 {
8940 this.Core.Write(ErrorMessages.UnexpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Company")); 7969 this.Core.Write(ErrorMessages.UnexpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Company"));
8941 } 7970 }
8942 this.ProcessProperties(sourceLineNumbers, name, value); 7971 this.AddPrivateProperty(sourceLineNumbers, name, value);
8943 } 7972 }
8944 } 7973 }
8945 7974
8946 /// <summary> 7975 /// <summary>
8947 /// Parses a patch sequence element. 7976 /// Adds a row to the properties table.
8948 /// </summary> 7977 /// </summary>
8949 /// <param name="node">The element to parse.</param> 7978 /// <param name="sourceLineNumbers">Source line numbers.</param>
8950 private void ParsePatchSequenceElement(XElement node) 7979 /// <param name="name">Name of the property.</param>
7980 /// <param name="value">Value of the property.</param>
7981 private void AddPrivateProperty(SourceLineNumber sourceLineNumbers, string name, string value)
8951 { 7982 {
8952 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
8953 string family = null;
8954 string target = null;
8955 string sequence = null;
8956 var attributes = 0;
8957
8958 foreach (var attrib in node.Attributes())
8959 {
8960 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
8961 {
8962 switch (attrib.Name.LocalName)
8963 {
8964 case "PatchFamily":
8965 family = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
8966 break;
8967 case "ProductCode":
8968 if (null != target)
8969 {
8970 this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "Target", "TargetImage"));
8971 }
8972 target = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false);
8973 break;
8974 case "Target":
8975 if (null != target)
8976 {
8977 this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "TargetImage", "ProductCode"));
8978 }
8979 this.Core.Write(WarningMessages.DeprecatedPatchSequenceTargetAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
8980 target = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
8981 break;
8982 case "TargetImage":
8983 if (null != target)
8984 {
8985 this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "Target", "ProductCode"));
8986 }
8987 target = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
8988 this.Core.CreateSimpleReference(sourceLineNumbers, "TargetImages", target);
8989 break;
8990 case "Sequence":
8991 sequence = this.Core.GetAttributeVersionValue(sourceLineNumbers, attrib);
8992 break;
8993 case "Supersede":
8994 if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
8995 {
8996 attributes |= 0x1;
8997 }
8998 break;
8999 default:
9000 this.Core.UnexpectedAttribute(node, attrib);
9001 break;
9002 }
9003 }
9004 else
9005 {
9006 this.Core.ParseExtensionAttribute(node, attrib);
9007 }
9008 }
9009
9010 if (null == family)
9011 {
9012 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "PatchFamily"));
9013 }
9014
9015 this.Core.ParseForExtensionElements(node);
9016
9017 if (!this.Core.EncounteredError) 7983 if (!this.Core.EncounteredError)
9018 { 7984 {
9019 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PatchSequence); 7985 var tuple = new PropertyTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, name))
9020 row.Set(0, family);
9021 row.Set(1, target);
9022 if (!String.IsNullOrEmpty(sequence))
9023 { 7986 {
9024 row.Set(2, sequence); 7987 Value = value
9025 } 7988 };
9026 row.Set(3, attributes); 7989
7990 this.Core.AddTuple(tuple);
9027 } 7991 }
9028 } 7992 }
9029 7993
@@ -9070,82 +8034,7 @@ namespace WixToolset.Core
9070 8034
9071 return id; 8035 return id;
9072 } 8036 }
9073 8037
9074 /// <summary>
9075 /// Parses a TargetProductCodes element.
9076 /// </summary>
9077 /// <param name="node">The element to parse.</param>
9078 private void ParseTargetProductCodesElement(XElement node)
9079 {
9080 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
9081 var replace = false;
9082 var targetProductCodes = new List<string>();
9083
9084 foreach (var attrib in node.Attributes())
9085 {
9086 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
9087 {
9088 switch (attrib.Name.LocalName)
9089 {
9090 case "Replace":
9091 replace = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
9092 break;
9093 default:
9094 this.Core.UnexpectedAttribute(node, attrib);
9095 break;
9096 }
9097 }
9098 else
9099 {
9100 this.Core.ParseExtensionAttribute(node, attrib);
9101 }
9102 }
9103
9104 foreach (var child in node.Elements())
9105 {
9106 if (CompilerCore.WixNamespace == child.Name.Namespace)
9107 {
9108 switch (child.Name.LocalName)
9109 {
9110 case "TargetProductCode":
9111 var id = this.ParseTargetProductCodeElement(child);
9112 if (0 == String.CompareOrdinal("*", id))
9113 {
9114 this.Core.Write(ErrorMessages.IllegalAttributeValueWhenNested(sourceLineNumbers, child.Name.LocalName, "Id", id, node.Name.LocalName));
9115 }
9116 else
9117 {
9118 targetProductCodes.Add(id);
9119 }
9120 break;
9121 default:
9122 this.Core.UnexpectedElement(node, child);
9123 break;
9124 }
9125 }
9126 else
9127 {
9128 this.Core.ParseExtensionElement(node, child);
9129 }
9130 }
9131
9132 if (!this.Core.EncounteredError)
9133 {
9134 // By default, target ProductCodes should be added.
9135 if (!replace)
9136 {
9137 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixPatchTarget);
9138 row.Set(0, "*");
9139 }
9140
9141 foreach (var targetProductCode in targetProductCodes)
9142 {
9143 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixPatchTarget);
9144 row.Set(0, targetProductCode);
9145 }
9146 }
9147 }
9148
9149 /// <summary> 8038 /// <summary>
9150 /// Parses a ReplacePatch element. 8039 /// Parses a ReplacePatch element.
9151 /// </summary> 8040 /// </summary>
@@ -9227,402 +8116,6 @@ namespace WixToolset.Core
9227 } 8116 }
9228 8117
9229 /// <summary> 8118 /// <summary>
9230 /// Parses an patch element.
9231 /// </summary>
9232 /// <param name="node">The element to parse.</param>
9233 private void ParsePatchElement(XElement node)
9234 {
9235 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
9236 string patchId = null;
9237 var codepage = 0;
9238 ////bool versionMismatches = false;
9239 ////bool productMismatches = false;
9240 var allowRemoval = false;
9241 string classification = null;
9242 string clientPatchId = null;
9243 string description = null;
9244 string displayName = null;
9245 string comments = null;
9246 string manufacturer = null;
9247 var minorUpdateTargetRTM = YesNoType.NotSet;
9248 string moreInfoUrl = null;
9249 var optimizeCA = CompilerConstants.IntegerNotSet;
9250 var optimizedInstallMode = YesNoType.NotSet;
9251 string targetProductName = null;
9252 // string replaceGuids = String.Empty;
9253 var apiPatchingSymbolFlags = 0;
9254 var optimizePatchSizeForLargeFiles = false;
9255
9256 foreach (var attrib in node.Attributes())
9257 {
9258 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
9259 {
9260 switch (attrib.Name.LocalName)
9261 {
9262 case "Id":
9263 patchId = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, true);
9264 break;
9265 case "Codepage":
9266 codepage = this.Core.GetAttributeCodePageValue(sourceLineNumbers, attrib);
9267 break;
9268 case "AllowMajorVersionMismatches":
9269 ////versionMismatches = (YesNoType.Yes == this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib));
9270 break;
9271 case "AllowProductCodeMismatches":
9272 ////productMismatches = (YesNoType.Yes == this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib));
9273 break;
9274 case "AllowRemoval":
9275 allowRemoval = (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib));
9276 break;
9277 case "Classification":
9278 classification = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
9279 break;
9280 case "ClientPatchId":
9281 clientPatchId = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
9282 break;
9283 case "Description":
9284 description = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
9285 break;
9286 case "DisplayName":
9287 displayName = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
9288 break;
9289 case "Comments":
9290 comments = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
9291 break;
9292 case "Manufacturer":
9293 manufacturer = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
9294 break;
9295 case "MinorUpdateTargetRTM":
9296 minorUpdateTargetRTM = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
9297 break;
9298 case "MoreInfoURL":
9299 moreInfoUrl = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
9300 break;
9301 case "OptimizedInstallMode":
9302 optimizedInstallMode = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
9303 break;
9304 case "TargetProductName":
9305 targetProductName = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
9306 break;
9307 case "ApiPatchingSymbolNoImagehlpFlag":
9308 apiPatchingSymbolFlags |= (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) ? (int)PatchSymbolFlagsType.PATCH_SYMBOL_NO_IMAGEHLP : 0;
9309 break;
9310 case "ApiPatchingSymbolNoFailuresFlag":
9311 apiPatchingSymbolFlags |= (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) ? (int)PatchSymbolFlagsType.PATCH_SYMBOL_NO_FAILURES : 0;
9312 break;
9313 case "ApiPatchingSymbolUndecoratedTooFlag":
9314 apiPatchingSymbolFlags |= (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) ? (int)PatchSymbolFlagsType.PATCH_SYMBOL_UNDECORATED_TOO : 0;
9315 break;
9316 case "OptimizePatchSizeForLargeFiles":
9317 optimizePatchSizeForLargeFiles = (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib));
9318 break;
9319 default:
9320 this.Core.UnexpectedAttribute(node, attrib);
9321 break;
9322 }
9323 }
9324 else
9325 {
9326 this.Core.ParseExtensionAttribute(node, attrib);
9327 }
9328 }
9329
9330 if (patchId == null || patchId == "*")
9331 {
9332 // auto-generate at compile time, since this value gets dispersed to several locations
9333 patchId = Common.GenerateGuid();
9334 }
9335 this.activeName = patchId;
9336
9337 if (null == this.activeName)
9338 {
9339 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
9340 }
9341 if (null == classification)
9342 {
9343 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Classification"));
9344 }
9345 if (null == clientPatchId)
9346 {
9347 clientPatchId = String.Concat("_", new Guid(patchId).ToString("N", CultureInfo.InvariantCulture).ToUpper(CultureInfo.InvariantCulture));
9348 }
9349 if (null == description)
9350 {
9351 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Description"));
9352 }
9353 if (null == displayName)
9354 {
9355 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "DisplayName"));
9356 }
9357 if (null == manufacturer)
9358 {
9359 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Manufacturer"));
9360 }
9361
9362 this.Core.CreateActiveSection(this.activeName, SectionType.Patch, codepage, this.Context.CompilationId);
9363
9364 foreach (var child in node.Elements())
9365 {
9366 if (CompilerCore.WixNamespace == child.Name.Namespace)
9367 {
9368 switch (child.Name.LocalName)
9369 {
9370 case "PatchInformation":
9371 this.ParsePatchInformationElement(child);
9372 break;
9373 case "Media":
9374 this.ParseMediaElement(child, patchId);
9375 break;
9376 case "OptimizeCustomActions":
9377 optimizeCA = this.ParseOptimizeCustomActionsElement(child);
9378 break;
9379 case "PatchFamily":
9380 this.ParsePatchFamilyElement(child, ComplexReferenceParentType.Patch, patchId);
9381 break;
9382 case "PatchFamilyRef":
9383 this.ParsePatchFamilyRefElement(child, ComplexReferenceParentType.Patch, patchId);
9384 break;
9385 case "PatchFamilyGroup":
9386 this.ParsePatchFamilyGroupElement(child, ComplexReferenceParentType.Patch, patchId);
9387 break;
9388 case "PatchFamilyGroupRef":
9389 this.ParsePatchFamilyGroupRefElement(child, ComplexReferenceParentType.Patch, patchId);
9390 break;
9391 case "PatchProperty":
9392 this.ParsePatchPropertyElement(child, true);
9393 break;
9394 case "TargetProductCodes":
9395 this.ParseTargetProductCodesElement(child);
9396 break;
9397 default:
9398 this.Core.UnexpectedElement(node, child);
9399 break;
9400 }
9401 }
9402 else
9403 {
9404 this.Core.ParseExtensionElement(node, child);
9405 }
9406 }
9407
9408 if (!this.Core.EncounteredError)
9409 {
9410 var patchIdRow = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixPatchId);
9411 patchIdRow.Set(0, patchId);
9412 patchIdRow.Set(1, clientPatchId);
9413 patchIdRow.Set(2, optimizePatchSizeForLargeFiles);
9414 patchIdRow.Set(3, apiPatchingSymbolFlags);
9415
9416 if (allowRemoval)
9417 {
9418 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiPatchMetadata);
9419 row.Set(1, "AllowRemoval");
9420 row.Set(2, allowRemoval ? "1" : "0");
9421 }
9422
9423 if (null != classification)
9424 {
9425 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiPatchMetadata);
9426 row.Set(1, "Classification");
9427 row.Set(2, classification);
9428 }
9429
9430 // always generate the CreationTimeUTC
9431 {
9432 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiPatchMetadata);
9433 row.Set(1, "CreationTimeUTC");
9434 row.Set(2, DateTime.UtcNow.ToString("MM-dd-yy HH:mm", CultureInfo.InvariantCulture));
9435 }
9436
9437 if (null != description)
9438 {
9439 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiPatchMetadata);
9440 row.Set(1, "Description");
9441 row.Set(2, description);
9442 }
9443
9444 if (null != displayName)
9445 {
9446 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiPatchMetadata);
9447 row.Set(1, "DisplayName");
9448 row.Set(2, displayName);
9449 }
9450
9451 if (null != manufacturer)
9452 {
9453 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiPatchMetadata);
9454 row.Set(1, "ManufacturerName");
9455 row.Set(2, manufacturer);
9456 }
9457
9458 if (YesNoType.NotSet != minorUpdateTargetRTM)
9459 {
9460 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiPatchMetadata);
9461 row.Set(1, "MinorUpdateTargetRTM");
9462 row.Set(2, YesNoType.Yes == minorUpdateTargetRTM ? "1" : "0");
9463 }
9464
9465 if (null != moreInfoUrl)
9466 {
9467 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiPatchMetadata);
9468 row.Set(1, "MoreInfoURL");
9469 row.Set(2, moreInfoUrl);
9470 }
9471
9472 if (CompilerConstants.IntegerNotSet != optimizeCA)
9473 {
9474 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiPatchMetadata);
9475 row.Set(1, "OptimizeCA");
9476 row.Set(2, optimizeCA.ToString(CultureInfo.InvariantCulture));
9477 }
9478
9479 if (YesNoType.NotSet != optimizedInstallMode)
9480 {
9481 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiPatchMetadata);
9482 row.Set(1, "OptimizedInstallMode");
9483 row.Set(2, YesNoType.Yes == optimizedInstallMode ? "1" : "0");
9484 }
9485
9486 if (null != targetProductName)
9487 {
9488 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiPatchMetadata);
9489 row.Set(1, "TargetProductName");
9490 row.Set(2, targetProductName);
9491 }
9492
9493 if (null != comments)
9494 {
9495 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixPatchMetadata);
9496 row.Set(0, "Comments");
9497 row.Set(1, comments);
9498 }
9499 }
9500 // TODO: do something with versionMismatches and productMismatches
9501 }
9502
9503 /// <summary>
9504 /// Parses a PatchFamily element.
9505 /// </summary>
9506 /// <param name="node">The element to parse.</param>
9507 private void ParsePatchFamilyElement(XElement node, ComplexReferenceParentType parentType, string parentId)
9508 {
9509 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
9510 Identifier id = null;
9511 string productCode = null;
9512 string version = null;
9513 var attributes = 0;
9514
9515 foreach (var attrib in node.Attributes())
9516 {
9517 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
9518 {
9519 switch (attrib.Name.LocalName)
9520 {
9521 case "Id":
9522 id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib);
9523 break;
9524 case "ProductCode":
9525 productCode = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false);
9526 break;
9527 case "Version":
9528 version = this.Core.GetAttributeVersionValue(sourceLineNumbers, attrib);
9529 break;
9530 case "Supersede":
9531 if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
9532 {
9533 attributes |= 0x1;
9534 }
9535 break;
9536 default:
9537 this.Core.UnexpectedAttribute(node, attrib);
9538 break;
9539 }
9540 }
9541 else
9542 {
9543 this.Core.ParseExtensionAttribute(node, attrib);
9544 }
9545 }
9546
9547 if (null == id)
9548 {
9549 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
9550 id = Identifier.Invalid;
9551 }
9552
9553 if (String.IsNullOrEmpty(version))
9554 {
9555 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Version"));
9556 }
9557 else if (!CompilerCore.IsValidProductVersion(version))
9558 {
9559 this.Core.Write(ErrorMessages.InvalidProductVersion(sourceLineNumbers, version));
9560 }
9561
9562 // find unexpected child elements
9563 foreach (var child in node.Elements())
9564 {
9565 if (CompilerCore.WixNamespace == child.Name.Namespace)
9566 {
9567 switch (child.Name.LocalName)
9568 {
9569 case "All":
9570 this.ParseAllElement(child);
9571 break;
9572 case "BinaryRef":
9573 this.ParsePatchChildRefElement(child, "Binary");
9574 break;
9575 case "ComponentRef":
9576 this.ParsePatchChildRefElement(child, "Component");
9577 break;
9578 case "CustomActionRef":
9579 this.ParsePatchChildRefElement(child, "CustomAction");
9580 break;
9581 case "DirectoryRef":
9582 this.ParsePatchChildRefElement(child, "Directory");
9583 break;
9584 case "DigitalCertificateRef":
9585 this.ParsePatchChildRefElement(child, "MsiDigitalCertificate");
9586 break;
9587 case "FeatureRef":
9588 this.ParsePatchChildRefElement(child, "Feature");
9589 break;
9590 case "IconRef":
9591 this.ParsePatchChildRefElement(child, "Icon");
9592 break;
9593 case "PropertyRef":
9594 this.ParsePatchChildRefElement(child, "Property");
9595 break;
9596 case "UIRef":
9597 this.ParsePatchChildRefElement(child, "WixUI");
9598 break;
9599 default:
9600 this.Core.UnexpectedElement(node, child);
9601 break;
9602 }
9603 }
9604 else
9605 {
9606 this.Core.ParseExtensionElement(node, child);
9607 }
9608 }
9609
9610
9611 if (!this.Core.EncounteredError)
9612 {
9613 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiPatchSequence, id);
9614 row.Set(1, productCode);
9615 row.Set(2, version);
9616 row.Set(3, attributes);
9617
9618 if (ComplexReferenceParentType.Unknown != parentType)
9619 {
9620 this.Core.CreateComplexReference(sourceLineNumbers, parentType, parentId, null, ComplexReferenceChildType.PatchFamily, id.Id, ComplexReferenceParentType.Patch == parentType);
9621 }
9622 }
9623 }
9624
9625 /// <summary>
9626 /// Parses the All element under a PatchFamily. 8119 /// Parses the All element under a PatchFamily.
9627 /// </summary> 8120 /// </summary>
9628 /// <param name="node">The element to parse.</param> 8121 /// <param name="node">The element to parse.</param>
@@ -9650,7 +8143,13 @@ namespace WixToolset.Core
9650 8143
9651 if (!this.Core.EncounteredError) 8144 if (!this.Core.EncounteredError)
9652 { 8145 {
9653 this.Core.CreatePatchFamilyChildReference(sourceLineNumbers, "*", "*"); 8146 var tuple = new WixPatchRefTuple(sourceLineNumbers)
8147 {
8148 Table = "*",
8149 PrimaryKeys = "*"
8150 };
8151
8152 this.Core.AddTuple(tuple);
9654 } 8153 }
9655 } 8154 }
9656 8155
@@ -9693,7 +8192,13 @@ namespace WixToolset.Core
9693 8192
9694 if (!this.Core.EncounteredError) 8193 if (!this.Core.EncounteredError)
9695 { 8194 {
9696 this.Core.CreatePatchFamilyChildReference(sourceLineNumbers, tableName, id); 8195 var tuple = new WixPatchRefTuple(sourceLineNumbers)
8196 {
8197 Table = tableName,
8198 PrimaryKeys = id
8199 };
8200
8201 this.Core.AddTuple(tuple);
9697 } 8202 }
9698 } 8203 }
9699 8204
@@ -9770,9 +8275,13 @@ namespace WixToolset.Core
9770 8275
9771 if (!this.Core.EncounteredError) 8276 if (!this.Core.EncounteredError)
9772 { 8277 {
9773 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixPatchBaseline, id); 8278 var tuple = new WixPatchBaselineTuple(sourceLineNumbers, id)
9774 row.Set(1, diskId); 8279 {
9775 row.Set(2, (int)validationFlags); 8280 DiskId = diskId,
8281 ValidationFlags = validationFlags
8282 };
8283
8284 this.Core.AddTuple(tuple);
9776 } 8285 }
9777 } 8286 }
9778 8287
@@ -9948,21 +8457,5 @@ namespace WixToolset.Core
9948 } 8457 }
9949 } 8458 }
9950 } 8459 }
9951
9952 /// <summary>
9953 /// Adds a row to the properties table.
9954 /// </summary>
9955 /// <param name="sourceLineNumbers">Source line numbers.</param>
9956 /// <param name="name">Name of the property.</param>
9957 /// <param name="value">Value of the property.</param>
9958 private void ProcessProperties(SourceLineNumber sourceLineNumbers, string name, string value)
9959 {
9960 if (!this.Core.EncounteredError)
9961 {
9962 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Properties);
9963 row.Set(0, name);
9964 row.Set(1, value);
9965 }
9966 }
9967 } 8460 }
9968} 8461}
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
17 using WixToolset.Extensibility; 17 using WixToolset.Extensibility;
18 using WixToolset.Extensibility.Data; 18 using WixToolset.Extensibility.Data;
19 using WixToolset.Extensibility.Services; 19 using WixToolset.Extensibility.Services;
20 using Wix = WixToolset.Data.Serialize;
21 20
22 internal enum ValueListKind 21 internal enum ValueListKind
23 { 22 {
@@ -50,9 +49,7 @@ namespace WixToolset.Core
50 private const string IllegalLongFilenameCharacters = @"[\\\?|><:/\*""]"; // illegal: \ ? | > < : / * " 49 private const string IllegalLongFilenameCharacters = @"[\\\?|><:/\*""]"; // illegal: \ ? | > < : / * "
51 private static readonly Regex IllegalLongFilename = new Regex(IllegalLongFilenameCharacters, RegexOptions.Compiled); 50 private static readonly Regex IllegalLongFilename = new Regex(IllegalLongFilenameCharacters, RegexOptions.Compiled);
52 51
53 public const int DefaultMaximumUncompressedMediaSize = 200; // Default value is 200 MB 52 //public const int DefaultMaximumUncompressedMediaSize = 200; // Default value is 200 MB
54 public const int MinValueOfMaxCabSizeForLargeFileSplitting = 20; // 20 MB
55 public const int MaxValueOfMaxCabSizeForLargeFileSplitting = 2 * 1024; // 2048 MB (i.e. 2 GB)
56 53
57 54
58 // Built-in variables (from burn\engine\variable.cpp, "vrgBuiltInVariables", around line 113) 55 // Built-in variables (from burn\engine\variable.cpp, "vrgBuiltInVariables", around line 113)
@@ -354,43 +351,20 @@ namespace WixToolset.Core
354 } 351 }
355 352
356 /// <summary> 353 /// <summary>
357 /// Creates a row in the active section. 354 /// Creates a tuple in the active section.
358 /// </summary> 355 /// </summary>
359 /// <param name="sourceLineNumbers">Source and line number of current row.</param> 356 /// <param name="sourceLineNumbers">Source and line number of current row.</param>
360 /// <param name="tupleType">Name of table to create row in.</param> 357 /// <param name="tupleType">Type of tuple to create.</param>
361 /// <returns>New row.</returns> 358 /// <param name="identifier">Optional identifier.</param>
362 public IntermediateTuple CreateRow(SourceLineNumber sourceLineNumbers, TupleDefinitionType tupleType, Identifier identifier = null) 359 /// <returns>New tuple.</returns>
363 { 360 public IntermediateTuple CreateTuple(SourceLineNumber sourceLineNumbers, TupleDefinitionType tupleType, Identifier identifier = null)
364 return this.CreateRow(sourceLineNumbers, tupleType, this.ActiveSection, identifier);
365 }
366
367 /// <summary>
368 /// Creates a row in the active given <paramref name="section"/>.
369 /// </summary>
370 /// <param name="sourceLineNumbers">Source and line number of current row.</param>
371 /// <param name="tupleType">Name of table to create row in.</param>
372 /// <param name="section">The section to which the row is added. If null, the row is added to the active section.</param>
373 /// <returns>New row.</returns>
374 internal IntermediateTuple CreateRow(SourceLineNumber sourceLineNumbers, TupleDefinitionType tupleType, IntermediateSection section, Identifier identifier = null)
375 { 361 {
376 var tupleDefinition = TupleDefinitions.ByType(tupleType); 362 var tupleDefinition = TupleDefinitions.ByType(tupleType);
377 var row = tupleDefinition.CreateTuple(sourceLineNumbers, identifier); 363 var tuple = tupleDefinition.CreateTuple(sourceLineNumbers, identifier);
378 364
379 if (null != identifier) 365 this.ActiveSection.Tuples.Add(tuple);
380 {
381 if (row.Definition.FieldDefinitions[0].Type == IntermediateFieldType.Number)
382 {
383 row.Set(0, Convert.ToInt32(identifier.Id));
384 }
385 else
386 {
387 row.Set(0, identifier.Id);
388 }
389 }
390
391 section.Tuples.Add(row);
392 366
393 return row; 367 return tuple;
394 } 368 }
395 369
396 /// <summary> 370 /// <summary>
@@ -406,20 +380,6 @@ namespace WixToolset.Core
406 } 380 }
407 381
408 /// <summary> 382 /// <summary>
409 /// 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.
410 /// </summary>
411 /// <param name="sourceLineNumbers">Source and line number of current row.</param>
412 /// <param name="tableName">Name of table to create row in.</param>
413 /// <param name="primaryKeys">Array of keys that make up the primary key of the table.</param>
414 /// <returns>New row.</returns>
415 public void CreatePatchFamilyChildReference(SourceLineNumber sourceLineNumbers, string tableName, params string[] primaryKeys)
416 {
417 var patchReferenceRow = this.CreateRow(sourceLineNumbers, TupleDefinitionType.WixPatchRef);
418 patchReferenceRow.Set(0, tableName);
419 patchReferenceRow.Set(1, String.Join("/", primaryKeys));
420 }
421
422 /// <summary>
423 /// Creates a Registry row in the active section. 383 /// Creates a Registry row in the active section.
424 /// </summary> 384 /// </summary>
425 /// <param name="sourceLineNumbers">Source and line number of the current row.</param> 385 /// <param name="sourceLineNumbers">Source and line number of the current row.</param>
@@ -430,7 +390,7 @@ namespace WixToolset.Core
430 /// <param name="componentId">The component which will control installation/uninstallation of the registry entry.</param> 390 /// <param name="componentId">The component which will control installation/uninstallation of the registry entry.</param>
431 public Identifier CreateRegistryRow(SourceLineNumber sourceLineNumbers, RegistryRootType root, string key, string name, string value, string componentId) 391 public Identifier CreateRegistryRow(SourceLineNumber sourceLineNumbers, RegistryRootType root, string key, string name, string value, string componentId)
432 { 392 {
433 return this.parseHelper.CreateRegistryRow(this.ActiveSection, sourceLineNumbers, root, key, name, value, componentId, true); 393 return this.parseHelper.CreateRegistryTuple(this.ActiveSection, sourceLineNumbers, root, key, name, value, componentId, true);
434 } 394 }
435 395
436 /// <summary> 396 /// <summary>
@@ -466,7 +426,7 @@ namespace WixToolset.Core
466 { 426 {
467 if (!this.EncounteredError) 427 if (!this.EncounteredError)
468 { 428 {
469 this.parseHelper.CreateWixGroupRow(this.ActiveSection, sourceLineNumbers, parentType, parentId, childType, childId); 429 this.parseHelper.CreateWixGroupTuple(this.ActiveSection, sourceLineNumbers, parentType, parentId, childType, childId);
470 } 430 }
471 } 431 }
472 432
@@ -753,39 +713,6 @@ namespace WixToolset.Core
753 } 713 }
754 714
755 /// <summary> 715 /// <summary>
756 /// Gets a yes/no/always value and displays an error for an illegal value.
757 /// </summary>
758 /// <param name="sourceLineNumbers">Source line information about the owner element.</param>
759 /// <param name="attribute">The attribute containing the value to get.</param>
760 /// <returns>The attribute's YesNoAlwaysType value.</returns>
761 [SuppressMessage("Microsoft.Design", "CA1059:MembersShouldNotExposeCertainConcreteTypes")]
762 public YesNoAlwaysType GetAttributeYesNoAlwaysValue(SourceLineNumber sourceLineNumbers, XAttribute attribute)
763 {
764 string value = this.GetAttributeValue(sourceLineNumbers, attribute);
765
766 if (0 < value.Length)
767 {
768 switch (Wix.Enums.ParseYesNoAlwaysType(value))
769 {
770 case Wix.YesNoAlwaysType.@always:
771 return YesNoAlwaysType.Always;
772 case Wix.YesNoAlwaysType.no:
773 return YesNoAlwaysType.No;
774 case Wix.YesNoAlwaysType.yes:
775 return YesNoAlwaysType.Yes;
776 case Wix.YesNoAlwaysType.NotSet:
777 // Previous code never returned 'NotSet'!
778 break;
779 default:
780 this.Write(ErrorMessages.IllegalYesNoAlwaysValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
781 break;
782 }
783 }
784
785 return YesNoAlwaysType.IllegalValue;
786 }
787
788 /// <summary>
789 /// Gets a short filename value and displays an error for an illegal short filename value. 716 /// Gets a short filename value and displays an error for an illegal short filename value.
790 /// </summary> 717 /// </summary>
791 /// <param name="sourceLineNumbers">Source line information about the owner element.</param> 718 /// <param name="sourceLineNumbers">Source line information about the owner element.</param>
@@ -855,57 +782,6 @@ namespace WixToolset.Core
855 } 782 }
856 783
857 /// <summary> 784 /// <summary>
858 /// Gets an InstallUninstallType value and displays an error for an illegal value.
859 /// </summary>
860 /// <param name="sourceLineNumbers">Source line information about the owner element.</param>
861 /// <param name="attribute">The attribute containing the value to get.</param>
862 /// <returns>The attribute's InstallUninstallType value.</returns>
863 [SuppressMessage("Microsoft.Design", "CA1059:MembersShouldNotExposeCertainConcreteTypes")]
864 public Wix.InstallUninstallType GetAttributeInstallUninstallValue(SourceLineNumber sourceLineNumbers, XAttribute attribute)
865 {
866 Wix.InstallUninstallType installUninstall = Wix.InstallUninstallType.NotSet;
867 string value = this.GetAttributeValue(sourceLineNumbers, attribute);
868
869 if (0 < value.Length)
870 {
871 installUninstall = Wix.Enums.ParseInstallUninstallType(value);
872
873 if (Wix.InstallUninstallType.IllegalValue == installUninstall)
874 {
875 // TODO: Find a way to expose the valid values programatically!
876 this.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value,
877 "install", "uninstall", "both"));
878 }
879 }
880
881 return installUninstall;
882 }
883
884 /// <summary>
885 /// Gets an ExitType value and displays an error for an illegal value.
886 /// </summary>
887 /// <param name="sourceLineNumbers">Source line information about the owner element.</param>
888 /// <param name="attribute">The attribute containing the value to get.</param>
889 /// <returns>The attribute's ExitType value.</returns>
890 [SuppressMessage("Microsoft.Design", "CA1059:MembersShouldNotExposeCertainConcreteTypes")]
891 public Wix.ExitType GetAttributeExitValue(SourceLineNumber sourceLineNumbers, XAttribute attribute)
892 {
893 string value = this.GetAttributeValue(sourceLineNumbers, attribute);
894
895 Wix.ExitType result = Wix.ExitType.NotSet;
896 if (!Enum.TryParse<Wix.ExitType>(value, out result))
897 {
898 result = Wix.ExitType.IllegalValue;
899
900 // TODO: Find a way to expose the valid values programatically!
901 this.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value,
902 "success", "cancel", "error", "suspend"));
903 }
904
905 return result;
906 }
907
908 /// <summary>
909 /// Gets a Bundle variable value and displays an error for an illegal value. 785 /// Gets a Bundle variable value and displays an error for an illegal value.
910 /// </summary> 786 /// </summary>
911 /// <param name="sourceLineNumbers">Source line information about the owner element.</param> 787 /// <param name="sourceLineNumbers">Source line information about the owner element.</param>
@@ -1062,7 +938,7 @@ namespace WixToolset.Core
1062 internal void VerifyRequiredVersion(SourceLineNumber sourceLineNumbers, string requiredVersion) 938 internal void VerifyRequiredVersion(SourceLineNumber sourceLineNumbers, string requiredVersion)
1063 { 939 {
1064 // an null or empty string means any version will work 940 // an null or empty string means any version will work
1065 if (!string.IsNullOrEmpty(requiredVersion)) 941 if (!String.IsNullOrEmpty(requiredVersion))
1066 { 942 {
1067 Assembly caller = Assembly.GetCallingAssembly(); 943 Assembly caller = Assembly.GetCallingAssembly();
1068 AssemblyName name = caller.GetName(); 944 AssemblyName name = caller.GetName();
@@ -1147,7 +1023,7 @@ namespace WixToolset.Core
1147 /// <returns>Identifier for the newly created row.</returns> 1023 /// <returns>Identifier for the newly created row.</returns>
1148 internal Identifier CreateDirectoryRow(SourceLineNumber sourceLineNumbers, Identifier id, string parentId, string name, string shortName = null, string sourceName = null, string shortSourceName = null) 1024 internal Identifier CreateDirectoryRow(SourceLineNumber sourceLineNumbers, Identifier id, string parentId, string name, string shortName = null, string sourceName = null, string shortSourceName = null)
1149 { 1025 {
1150 return this.parseHelper.CreateDirectoryRow(this.ActiveSection, sourceLineNumbers, id, parentId, name, this.activeSectionInlinedDirectoryIds, shortName, sourceName, shortSourceName); 1026 return this.parseHelper.CreateDirectoryTuple(this.ActiveSection, sourceLineNumbers, id, parentId, name, this.activeSectionInlinedDirectoryIds, shortName, sourceName, shortSourceName);
1151 } 1027 }
1152 1028
1153 /// <summary> 1029 /// <summary>
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,13 +20,308 @@ namespace WixToolset.Core
20 internal partial class Compiler : ICompiler 20 internal partial class Compiler : ICompiler
21 { 21 {
22 /// <summary> 22 /// <summary>
23 /// Parses a product element.
24 /// </summary>
25 /// <param name="node">Element to parse.</param>
26 private void ParseProductElement(XElement node)
27 {
28 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
29 var codepage = 65001;
30 string productCode = "*";
31 string upgradeCode = null;
32 string manufacturer = null;
33 string version = null;
34 string symbols = null;
35
36 this.activeName = null;
37 this.activeLanguage = null;
38
39 foreach (var attrib in node.Attributes())
40 {
41 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
42 {
43 switch (attrib.Name.LocalName)
44 {
45 case "Id":
46 productCode = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, true);
47 break;
48 case "Codepage":
49 codepage = this.Core.GetAttributeCodePageValue(sourceLineNumbers, attrib);
50 break;
51 case "Language":
52 this.activeLanguage = this.Core.GetAttributeLocalizableIntegerValue(sourceLineNumbers, attrib, 0, Int16.MaxValue);
53 break;
54 case "Manufacturer":
55 manufacturer = this.Core.GetAttributeValue(sourceLineNumbers, attrib, EmptyRule.MustHaveNonWhitespaceCharacters);
56 if ("PUT-COMPANY-NAME-HERE" == manufacturer)
57 {
58 this.Core.Write(WarningMessages.PlaceholderValue(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, manufacturer));
59 }
60 break;
61 case "Name":
62 this.activeName = this.Core.GetAttributeValue(sourceLineNumbers, attrib, EmptyRule.MustHaveNonWhitespaceCharacters);
63 if ("PUT-PRODUCT-NAME-HERE" == this.activeName)
64 {
65 this.Core.Write(WarningMessages.PlaceholderValue(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, this.activeName));
66 }
67 break;
68 case "UpgradeCode":
69 upgradeCode = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false);
70 break;
71 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").
72 var verifiedVersion = this.Core.GetAttributeVersionValue(sourceLineNumbers, attrib);
73 if (!String.IsNullOrEmpty(verifiedVersion))
74 {
75 version = attrib.Value;
76 }
77 break;
78 default:
79 this.Core.UnexpectedAttribute(node, attrib);
80 break;
81 }
82 }
83 else
84 {
85 this.Core.ParseExtensionAttribute(node, attrib);
86 }
87 }
88
89 if (null == productCode)
90 {
91 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
92 }
93
94 if (null == this.activeLanguage)
95 {
96 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Language"));
97 }
98
99 if (null == manufacturer)
100 {
101 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Manufacturer"));
102 }
103
104 if (null == this.activeName)
105 {
106 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Name"));
107 }
108
109 if (null == upgradeCode)
110 {
111 this.Core.Write(WarningMessages.MissingUpgradeCode(sourceLineNumbers));
112 }
113
114 if (null == version)
115 {
116 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Version"));
117 }
118 else if (!CompilerCore.IsValidProductVersion(version))
119 {
120 this.Core.Write(ErrorMessages.InvalidProductVersion(sourceLineNumbers, version));
121 }
122
123 if (this.Core.EncounteredError)
124 {
125 return;
126 }
127
128 try
129 {
130 this.compilingProduct = true;
131 this.Core.CreateActiveSection(productCode, SectionType.Product, codepage, this.Context.CompilationId);
132
133 this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Public, "Manufacturer"), manufacturer, false, false, false, true);
134 this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Public, "ProductCode"), productCode, false, false, false, true);
135 this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Public, "ProductLanguage"), this.activeLanguage, false, false, false, true);
136 this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Public, "ProductName"), this.activeName, false, false, false, true);
137 this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Public, "ProductVersion"), version, false, false, false, true);
138 if (null != upgradeCode)
139 {
140 this.AddProperty(sourceLineNumbers, new Identifier(AccessModifier.Public, "UpgradeCode"), upgradeCode, false, false, false, true);
141 }
142
143 var contextValues = new Dictionary<string, string>
144 {
145 ["ProductLanguage"] = this.activeLanguage,
146 ["ProductVersion"] = version,
147 ["UpgradeCode"] = upgradeCode
148 };
149
150 var featureDisplay = 0;
151 foreach (var child in node.Elements())
152 {
153 if (CompilerCore.WixNamespace == child.Name.Namespace)
154 {
155 switch (child.Name.LocalName)
156 {
157 case "_locDefinition":
158 break;
159 case "AdminExecuteSequence":
160 this.ParseSequenceElement(child, SequenceTable.AdminExecuteSequence);
161 break;
162 case "AdminUISequence":
163 this.ParseSequenceElement(child, SequenceTable.AdminUISequence);
164 break;
165 case "AdvertiseExecuteSequence":
166 this.ParseSequenceElement(child, SequenceTable.AdvertiseExecuteSequence);
167 break;
168 case "InstallExecuteSequence":
169 this.ParseSequenceElement(child, SequenceTable.InstallExecuteSequence);
170 break;
171 case "InstallUISequence":
172 this.ParseSequenceElement(child, SequenceTable.InstallUISequence);
173 break;
174 case "AppId":
175 this.ParseAppIdElement(child, null, YesNoType.Yes, null, null, null);
176 break;
177 case "Binary":
178 this.ParseBinaryElement(child);
179 break;
180 case "ComplianceCheck":
181 this.ParseComplianceCheckElement(child);
182 break;
183 case "Component":
184 this.ParseComponentElement(child, ComplexReferenceParentType.Unknown, null, null, CompilerConstants.IntegerNotSet, null, null);
185 break;
186 case "ComponentGroup":
187 this.ParseComponentGroupElement(child, ComplexReferenceParentType.Unknown, null);
188 break;
189 case "Condition":
190 this.ParseConditionElement(child, node.Name.LocalName, null, null);
191 break;
192 case "CustomAction":
193 this.ParseCustomActionElement(child);
194 break;
195 case "CustomActionRef":
196 this.ParseSimpleRefElement(child, "CustomAction");
197 break;
198 case "CustomTable":
199 this.ParseCustomTableElement(child);
200 break;
201 case "Directory":
202 this.ParseDirectoryElement(child, null, CompilerConstants.IntegerNotSet, String.Empty);
203 break;
204 case "DirectoryRef":
205 this.ParseDirectoryRefElement(child);
206 break;
207 case "EmbeddedChainer":
208 this.ParseEmbeddedChainerElement(child);
209 break;
210 case "EmbeddedChainerRef":
211 this.ParseSimpleRefElement(child, "MsiEmbeddedChainer");
212 break;
213 case "EnsureTable":
214 this.ParseEnsureTableElement(child);
215 break;
216 case "Feature":
217 this.ParseFeatureElement(child, ComplexReferenceParentType.Product, productCode, ref featureDisplay);
218 break;
219 case "FeatureRef":
220 this.ParseFeatureRefElement(child, ComplexReferenceParentType.Product, productCode);
221 break;
222 case "FeatureGroupRef":
223 this.ParseFeatureGroupRefElement(child, ComplexReferenceParentType.Product, productCode);
224 break;
225 case "Icon":
226 this.ParseIconElement(child);
227 break;
228 case "InstanceTransforms":
229 this.ParseInstanceTransformsElement(child);
230 break;
231 case "MajorUpgrade":
232 this.ParseMajorUpgradeElement(child, contextValues);
233 break;
234 case "Media":
235 this.ParseMediaElement(child, null);
236 break;
237 case "MediaTemplate":
238 this.ParseMediaTemplateElement(child, null);
239 break;
240 case "Package":
241 this.ParsePackageElement(child, manufacturer, null);
242 break;
243 case "PackageCertificates":
244 case "PatchCertificates":
245 this.ParseCertificatesElement(child);
246 break;
247 case "Property":
248 this.ParsePropertyElement(child);
249 break;
250 case "PropertyRef":
251 this.ParseSimpleRefElement(child, "Property");
252 break;
253 case "SetDirectory":
254 this.ParseSetDirectoryElement(child);
255 break;
256 case "SetProperty":
257 this.ParseSetPropertyElement(child);
258 break;
259 case "SFPCatalog":
260 string parentName = null;
261 this.ParseSFPCatalogElement(child, ref parentName);
262 break;
263 case "SymbolPath":
264 if (null != symbols)
265 {
266 symbols += ";" + this.ParseSymbolPathElement(child);
267 }
268 else
269 {
270 symbols = this.ParseSymbolPathElement(child);
271 }
272 break;
273 case "UI":
274 this.ParseUIElement(child);
275 break;
276 case "UIRef":
277 this.ParseSimpleRefElement(child, "WixUI");
278 break;
279 case "Upgrade":
280 this.ParseUpgradeElement(child);
281 break;
282 case "WixVariable":
283 this.ParseWixVariableElement(child);
284 break;
285 default:
286 this.Core.UnexpectedElement(node, child);
287 break;
288 }
289 }
290 else
291 {
292 this.Core.ParseExtensionElement(node, child);
293 }
294 }
295
296 if (!this.Core.EncounteredError)
297 {
298 if (null != symbols)
299 {
300 var tuple = new WixDeltaPatchSymbolPathsTuple(sourceLineNumbers)
301 {
302 SymbolId = productCode,
303 SymbolType = SymbolPathType.Product,
304 SymbolPaths = symbols
305 };
306
307 this.Core.AddTuple(tuple);
308 }
309 }
310 }
311 finally
312 {
313 this.compilingProduct = false;
314 }
315 }
316
317 /// <summary>
23 /// Parses an odbc driver or translator element. 318 /// Parses an odbc driver or translator element.
24 /// </summary> 319 /// </summary>
25 /// <param name="node">Element to parse.</param> 320 /// <param name="node">Element to parse.</param>
26 /// <param name="componentId">Identifier of parent component.</param> 321 /// <param name="componentId">Identifier of parent component.</param>
27 /// <param name="fileId">Default identifer for driver/translator file.</param> 322 /// <param name="fileId">Default identifer for driver/translator file.</param>
28 /// <param name="table">Table we're processing for.</param> 323 /// <param name="tupleDefinitionType">Tuple type we're processing for.</param>
29 private void ParseODBCDriverOrTranslator(XElement node, string componentId, string fileId, TupleDefinitionType tableName) 324 private void ParseODBCDriverOrTranslator(XElement node, string componentId, string fileId, TupleDefinitionType tupleDefinitionType)
30 { 325 {
31 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); 326 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
32 Identifier id = null; 327 Identifier id = null;
@@ -76,7 +371,7 @@ namespace WixToolset.Core
76 } 371 }
77 372
78 // drivers have a few possible children 373 // drivers have a few possible children
79 if (TupleDefinitionType.ODBCDriver == tableName) 374 if (TupleDefinitionType.ODBCDriver == tupleDefinitionType)
80 { 375 {
81 // process any data sources for the driver 376 // process any data sources for the driver
82 foreach (var child in node.Elements()) 377 foreach (var child in node.Elements())
@@ -110,11 +405,11 @@ namespace WixToolset.Core
110 405
111 if (!this.Core.EncounteredError) 406 if (!this.Core.EncounteredError)
112 { 407 {
113 var row = this.Core.CreateRow(sourceLineNumbers, tableName, id); 408 var tuple = this.Core.CreateTuple(sourceLineNumbers, tupleDefinitionType, id);
114 row.Set(1, componentId); 409 tuple.Set(1, componentId);
115 row.Set(2, name); 410 tuple.Set(2, name);
116 row.Set(3, driver); 411 tuple.Set(3, driver);
117 row.Set(4, setup); 412 tuple.Set(4, setup);
118 } 413 }
119 } 414 }
120 415
@@ -123,8 +418,8 @@ namespace WixToolset.Core
123 /// </summary> 418 /// </summary>
124 /// <param name="node">Element to parse.</param> 419 /// <param name="node">Element to parse.</param>
125 /// <param name="parentId">Identifier of parent driver or translator.</param> 420 /// <param name="parentId">Identifier of parent driver or translator.</param>
126 /// <param name="tableName">Name of the table to create property in.</param> 421 /// <param name="tupleDefinitionType">Name of the table to create property in.</param>
127 private void ParseODBCProperty(XElement node, string parentId, TupleDefinitionType tableName) 422 private void ParseODBCProperty(XElement node, string parentId, TupleDefinitionType tupleDefinitionType)
128 { 423 {
129 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); 424 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
130 string id = null; 425 string id = null;
@@ -162,10 +457,10 @@ namespace WixToolset.Core
162 457
163 if (!this.Core.EncounteredError) 458 if (!this.Core.EncounteredError)
164 { 459 {
165 var row = this.Core.CreateRow(sourceLineNumbers, tableName); 460 var tuple = this.Core.CreateTuple(sourceLineNumbers, tupleDefinitionType, new Identifier(AccessModifier.Private, parentId, id));
166 row.Set(0, parentId); 461 tuple.Set(0, parentId);
167 row.Set(1, id); 462 tuple.Set(1, id);
168 row.Set(2, propertyValue); 463 tuple.Set(2, propertyValue);
169 } 464 }
170 } 465 }
171 466
@@ -264,11 +559,13 @@ namespace WixToolset.Core
264 559
265 if (!this.Core.EncounteredError) 560 if (!this.Core.EncounteredError)
266 { 561 {
267 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ODBCDataSource, id); 562 this.Core.AddTuple(new ODBCDataSourceTuple(sourceLineNumbers, id)
268 row.Set(1, componentId); 563 {
269 row.Set(2, name); 564 Component_ = componentId,
270 row.Set(3, driverName); 565 Description = name,
271 row.Set(4, registration); 566 DriverDescription = driverName,
567 Registration = registration
568 });
272 } 569 }
273 570
274 possibleKeyPath = id.Id; 571 possibleKeyPath = id.Id;
@@ -296,7 +593,6 @@ namespace WixToolset.Core
296 string platformValue = null; 593 string platformValue = null;
297 var security = YesNoDefaultType.Default; 594 var security = YesNoDefaultType.Default;
298 var sourceBits = (this.compilingModule ? 2 : 0); 595 var sourceBits = (this.compilingModule ? 2 : 0);
299 IntermediateTuple row;
300 var installPrivilegeSeen = false; 596 var installPrivilegeSeen = false;
301 var installScopeSeen = false; 597 var installScopeSeen = false;
302 598
@@ -333,7 +629,7 @@ namespace WixToolset.Core
333 case "AdminImage": 629 case "AdminImage":
334 if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) 630 if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
335 { 631 {
336 sourceBits = sourceBits | 4; 632 sourceBits |= 4;
337 } 633 }
338 break; 634 break;
339 case "Comments": 635 case "Comments":
@@ -348,7 +644,7 @@ namespace WixToolset.Core
348 } 644 }
349 else if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) 645 else if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
350 { 646 {
351 sourceBits = sourceBits | 2; 647 sourceBits |= 2;
352 } 648 }
353 break; 649 break;
354 case "Description": 650 case "Description":
@@ -363,7 +659,7 @@ namespace WixToolset.Core
363 installPrivilegeSeen = true; 659 installPrivilegeSeen = true;
364 break; 660 break;
365 case "limited": 661 case "limited":
366 sourceBits = sourceBits | 8; 662 sourceBits |= 8;
367 installPrivilegeSeen = true; 663 installPrivilegeSeen = true;
368 break; 664 break;
369 case "": 665 case "":
@@ -379,13 +675,15 @@ namespace WixToolset.Core
379 { 675 {
380 case "perMachine": 676 case "perMachine":
381 { 677 {
382 row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Property, new Identifier("ALLUSERS", AccessModifier.Public)); 678 this.Core.AddTuple(new PropertyTuple(sourceLineNumbers, new Identifier(AccessModifier.Public, "ALLUSERS"))
383 row.Set(1, "1"); 679 {
680 Value = "1"
681 });
384 installScopeSeen = true; 682 installScopeSeen = true;
385 } 683 }
386 break; 684 break;
387 case "perUser": 685 case "perUser":
388 sourceBits = sourceBits | 8; 686 sourceBits |= 8;
389 installScopeSeen = true; 687 installScopeSeen = true;
390 break; 688 break;
391 case "": 689 case "":
@@ -461,7 +759,7 @@ namespace WixToolset.Core
461 case "ShortNames": 759 case "ShortNames":
462 if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) 760 if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
463 { 761 {
464 sourceBits = sourceBits | 1; 762 sourceBits |= 1;
465 this.useShortFileNames = true; 763 this.useShortFileNames = true;
466 } 764 }
467 break; 765 break;
@@ -534,380 +832,75 @@ namespace WixToolset.Core
534 832
535 if (!this.Core.EncounteredError) 833 if (!this.Core.EncounteredError)
536 { 834 {
537 row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); 835 this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers)
538 row.Set(0, 1);
539 row.Set(1, codepage);
540
541 row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation);
542 row.Set(0, 2);
543 row.Set(1, "Installation Database");
544
545 row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation);
546 row.Set(0, 3);
547 row.Set(1, packageName);
548
549 row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation);
550 row.Set(0, 4);
551 row.Set(1, packageAuthor);
552
553 row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation);
554 row.Set(0, 5);
555 row.Set(1, keywords);
556
557 row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation);
558 row.Set(0, 6);
559 row.Set(1, comments);
560
561 row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation);
562 row.Set(0, 7);
563 row.Set(1, String.Format(CultureInfo.InvariantCulture, "{0};{1}", platform, packageLanguages));
564
565 row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation);
566 row.Set(0, 9);
567 row.Set(1, packageCode);
568
569 row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation);
570 row.Set(0, 14);
571 row.Set(1, msiVersion.ToString(CultureInfo.InvariantCulture));
572
573 row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation);
574 row.Set(0, 15);
575 row.Set(1, sourceBits.ToString(CultureInfo.InvariantCulture));
576
577 row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation);
578 row.Set(0, 19);
579 switch (security)
580 {
581 case YesNoDefaultType.No: // no restriction
582 row.Set(1, "0");
583 break;
584 case YesNoDefaultType.Default: // read-only recommended
585 row.Set(1, "2");
586 break;
587 case YesNoDefaultType.Yes: // read-only enforced
588 row.Set(1, "4");
589 break;
590 }
591 }
592 }
593
594 /// <summary>
595 /// Parses a patch metadata element.
596 /// </summary>
597 /// <param name="node">Element to parse.</param>
598 private void ParsePatchMetadataElement(XElement node)
599 {
600 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
601 var allowRemoval = YesNoType.NotSet;
602 string classification = null;
603 string creationTimeUtc = null;
604 string description = null;
605 string displayName = null;
606 string manufacturerName = null;
607 string minorUpdateTargetRTM = null;
608 string moreInfoUrl = null;
609 var optimizeCA = CompilerConstants.IntegerNotSet;
610 var optimizedInstallMode = YesNoType.NotSet;
611 string targetProductName = null;
612
613 foreach (var attrib in node.Attributes())
614 {
615 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
616 {
617 switch (attrib.Name.LocalName)
618 {
619 case "AllowRemoval":
620 allowRemoval = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
621 break;
622 case "Classification":
623 classification = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
624 break;
625 case "CreationTimeUTC":
626 creationTimeUtc = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
627 break;
628 case "Description":
629 description = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
630 break;
631 case "DisplayName":
632 displayName = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
633 break;
634 case "ManufacturerName":
635 manufacturerName = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
636 break;
637 case "MinorUpdateTargetRTM":
638 minorUpdateTargetRTM = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
639 break;
640 case "MoreInfoURL":
641 moreInfoUrl = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
642 break;
643 case "OptimizedInstallMode":
644 optimizedInstallMode = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
645 break;
646 case "TargetProductName":
647 targetProductName = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
648 break;
649 default:
650 this.Core.UnexpectedAttribute(node, attrib);
651 break;
652 }
653 }
654 else
655 {
656 this.Core.ParseExtensionAttribute(node, attrib);
657 }
658 }
659
660 if (YesNoType.NotSet == allowRemoval)
661 {
662 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "AllowRemoval"));
663 }
664
665 if (null == classification)
666 {
667 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Classification"));
668 }
669
670 if (null == description)
671 {
672 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Description"));
673 }
674
675 if (null == displayName)
676 {
677 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "DisplayName"));
678 }
679
680 if (null == manufacturerName)
681 {
682 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "ManufacturerName"));
683 }
684
685 if (null == moreInfoUrl)
686 {
687 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "MoreInfoURL"));
688 }
689
690 if (null == targetProductName)
691 {
692 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "TargetProductName"));
693 }
694
695 foreach (var child in node.Elements())
696 {
697 if (CompilerCore.WixNamespace == child.Name.Namespace)
698 {
699 switch (child.Name.LocalName)
700 {
701 case "CustomProperty":
702 this.ParseCustomPropertyElement(child);
703 break;
704 case "OptimizeCustomActions":
705 optimizeCA = this.ParseOptimizeCustomActionsElement(child);
706 break;
707 default:
708 this.Core.UnexpectedElement(node, child);
709 break;
710 }
711 }
712 else
713 {
714 this.Core.ParseExtensionElement(node, child);
715 }
716 }
717
718 if (!this.Core.EncounteredError)
719 {
720 if (YesNoType.NotSet != allowRemoval)
721 { 836 {
722 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PatchMetadata); 837 PropertyId = SumaryInformationType.Codepage,
723 row.Set(1, "AllowRemoval"); 838 Value = codepage
724 row.Set(2, YesNoType.Yes == allowRemoval ? "1" : "0"); 839 });
725 }
726 840
727 if (null != classification) 841 this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers)
728 { 842 {
729 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PatchMetadata); 843 PropertyId = SumaryInformationType.Title,
730 row.Set(1, "Classification"); 844 Value = "Installation Database"
731 row.Set(2, classification); 845 });
732 }
733 846
734 if (null != creationTimeUtc) 847 this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers)
735 { 848 {
736 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PatchMetadata); 849 PropertyId = SumaryInformationType.Subject,
737 row.Set(1, "CreationTimeUTC"); 850 Value = packageName
738 row.Set(2, creationTimeUtc); 851 });
739 }
740 852
741 if (null != description) 853 this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers)
742 { 854 {
743 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PatchMetadata); 855 PropertyId = SumaryInformationType.Author,
744 row.Set(1, "Description"); 856 Value = packageAuthor
745 row.Set(2, description); 857 });
746 }
747 858
748 if (null != displayName) 859 this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers)
749 { 860 {
750 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PatchMetadata); 861 PropertyId = SumaryInformationType.Keywords,
751 row.Set(1, "DisplayName"); 862 Value = keywords
752 row.Set(2, displayName); 863 });
753 }
754 864
755 if (null != manufacturerName) 865 this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers)
756 { 866 {
757 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PatchMetadata); 867 PropertyId = SumaryInformationType.Comments,
758 row.Set(1, "ManufacturerName"); 868 Value = comments
759 row.Set(2, manufacturerName); 869 });
760 }
761 870
762 if (null != minorUpdateTargetRTM) 871 this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers)
763 { 872 {
764 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PatchMetadata); 873 PropertyId = SumaryInformationType.PlatformAndLanguage,
765 row.Set(1, "MinorUpdateTargetRTM"); 874 Value = String.Format(CultureInfo.InvariantCulture, "{0};{1}", platform, packageLanguages)
766 row.Set(2, minorUpdateTargetRTM); 875 });
767 }
768 876
769 if (null != moreInfoUrl) 877 this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers)
770 { 878 {
771 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PatchMetadata); 879 PropertyId = SumaryInformationType.PackageCode,
772 row.Set(1, "MoreInfoURL"); 880 Value = packageCode
773 row.Set(2, moreInfoUrl); 881 });
774 }
775 882
776 if (CompilerConstants.IntegerNotSet != optimizeCA) 883 this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers)
777 { 884 {
778 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PatchMetadata); 885 PropertyId = SumaryInformationType.WindowsInstallerVersion,
779 row.Set(1, "OptimizeCA"); 886 Value = msiVersion.ToString(CultureInfo.InvariantCulture)
780 row.Set(2, optimizeCA.ToString(CultureInfo.InvariantCulture)); 887 });
781 }
782 888
783 if (YesNoType.NotSet != optimizedInstallMode) 889 this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers)
784 { 890 {
785 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PatchMetadata); 891 PropertyId = SumaryInformationType.WordCount,
786 row.Set(1, "OptimizedInstallMode"); 892 Value = sourceBits.ToString(CultureInfo.InvariantCulture)
787 row.Set(2, YesNoType.Yes == optimizedInstallMode ? "1" : "0"); 893 });
788 }
789 894
790 if (null != targetProductName) 895 this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers)
791 { 896 {
792 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PatchMetadata); 897 PropertyId = SumaryInformationType.Security,
793 row.Set(1, "TargetProductName"); 898 Value = YesNoDefaultType.No == security ? "0" : YesNoDefaultType.Yes == security ? "4" : "2"
794 row.Set(2, targetProductName); 899 });
795 }
796 } 900 }
797 } 901 }
798 902
799 /// <summary> 903 /// <summary>
800 /// Parses a custom property element for the PatchMetadata table.
801 /// </summary>
802 /// <param name="node">Element to parse.</param>
803 private void ParseCustomPropertyElement(XElement node)
804 {
805 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
806 string company = null;
807 string property = null;
808 string value = null;
809
810 foreach (var attrib in node.Attributes())
811 {
812 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
813 {
814 switch (attrib.Name.LocalName)
815 {
816 case "Company":
817 company = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
818 break;
819 case "Property":
820 property = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
821 break;
822 case "Value":
823 value = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
824 break;
825 default:
826 this.Core.UnexpectedAttribute(node, attrib);
827 break;
828 }
829 }
830 else
831 {
832 this.Core.ParseExtensionAttribute(node, attrib);
833 }
834 }
835
836 if (null == company)
837 {
838 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Company"));
839 }
840
841 if (null == property)
842 {
843 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Property"));
844 }
845
846 if (null == value)
847 {
848 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Value"));
849 }
850
851 this.Core.ParseForExtensionElements(node);
852
853 if (!this.Core.EncounteredError)
854 {
855 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.PatchMetadata);
856 row.Set(0, company);
857 row.Set(1, property);
858 row.Set(2, value);
859 }
860 }
861
862 /// <summary>
863 /// Parses the OptimizeCustomActions element.
864 /// </summary>
865 /// <param name="node">Element to parse.</param>
866 /// <returns>The combined integer value for callers to store as appropriate.</returns>
867 private int ParseOptimizeCustomActionsElement(XElement node)
868 {
869 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
870 var optimizeCA = OptimizeCA.None;
871
872 foreach (var attrib in node.Attributes())
873 {
874 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
875 {
876 switch (attrib.Name.LocalName)
877 {
878 case "SkipAssignment":
879 if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
880 {
881 optimizeCA |= OptimizeCA.SkipAssignment;
882 }
883 break;
884 case "SkipImmediate":
885 if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
886 {
887 optimizeCA |= OptimizeCA.SkipImmediate;
888 }
889 break;
890 case "SkipDeferred":
891 if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
892 {
893 optimizeCA |= OptimizeCA.SkipDeferred;
894 }
895 break;
896 default:
897 this.Core.UnexpectedAttribute(node, attrib);
898 break;
899 }
900 }
901 else
902 {
903 this.Core.ParseExtensionAttribute(node, attrib);
904 }
905 }
906
907 return (int)optimizeCA;
908 }
909
910 /// <summary>
911 /// Parses a patch information element. 904 /// Parses a patch information element.
912 /// </summary> 905 /// </summary>
913 /// <param name="node">Element to parse.</param> 906 /// <param name="node">Element to parse.</param>
@@ -976,73 +969,77 @@ namespace WixToolset.Core
976 969
977 if (!this.Core.EncounteredError) 970 if (!this.Core.EncounteredError)
978 { 971 {
979 // PID_CODEPAGE 972 this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers)
980 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); 973 {
981 row.Set(0, 1); 974 PropertyId = SumaryInformationType.Codepage,
982 row.Set(1, codepage); 975 Value = codepage
976 });
983 977
984 // PID_TITLE 978 this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers)
985 row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); 979 {
986 row.Set(0, 2); 980 PropertyId = SumaryInformationType.Title,
987 row.Set(1, "Patch"); 981 Value = "Patch"
982 });
988 983
989 // PID_SUBJECT
990 if (null != packageName) 984 if (null != packageName)
991 { 985 {
992 row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); 986 this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers)
993 row.Set(0, 3); 987 {
994 row.Set(1, packageName); 988 PropertyId = SumaryInformationType.Subject,
989 Value = packageName
990 });
995 } 991 }
996 992
997 // PID_AUTHOR
998 if (null != packageAuthor) 993 if (null != packageAuthor)
999 { 994 {
1000 row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); 995 this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers)
1001 row.Set(0, 4); 996 {
1002 row.Set(1, packageAuthor); 997 PropertyId = SumaryInformationType.Author,
998 Value = packageAuthor
999 });
1003 } 1000 }
1004 1001
1005 // PID_KEYWORDS
1006 if (null != keywords) 1002 if (null != keywords)
1007 { 1003 {
1008 row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); 1004 this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers)
1009 row.Set(0, 5); 1005 {
1010 row.Set(1, keywords); 1006 PropertyId = SumaryInformationType.Keywords,
1007 Value = keywords
1008 });
1011 } 1009 }
1012 1010
1013 // PID_COMMENTS
1014 if (null != comments) 1011 if (null != comments)
1015 { 1012 {
1016 row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); 1013 this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers)
1017 row.Set(0, 6); 1014 {
1018 row.Set(1, comments); 1015 PropertyId = SumaryInformationType.Comments,
1016 Value = comments
1017 });
1019 } 1018 }
1020 1019
1021 // PID_PAGECOUNT 1020 this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers)
1022 row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); 1021 {
1023 row.Set(0, 14); 1022 PropertyId = SumaryInformationType.WindowsInstallerVersion,
1024 row.Set(1, msiVersion.ToString(CultureInfo.InvariantCulture)); 1023 Value = msiVersion.ToString(CultureInfo.InvariantCulture)
1024 });
1025
1026 this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers)
1027 {
1028 PropertyId = SumaryInformationType.WordCount,
1029 Value = "0"
1030 });
1025 1031
1026 // PID_WORDCOUNT 1032 this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers)
1027 row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation); 1033 {
1028 row.Set(0, 15); 1034 PropertyId = SumaryInformationType.WindowsInstallerVersion,
1029 row.Set(1, "0"); 1035 Value = msiVersion.ToString(CultureInfo.InvariantCulture)
1036 });
1030 1037
1031 // PID_SECURITY 1038 this.Core.AddTuple(new SummaryInformationTuple(sourceLineNumbers)
1032 row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType._SummaryInformation);
1033 row.Set(0, 19);
1034 switch (security)
1035 { 1039 {
1036 case YesNoDefaultType.No: // no restriction 1040 PropertyId = SumaryInformationType.Security,
1037 row.Set(1, "0"); 1041 Value = YesNoDefaultType.No == security ? "0" : YesNoDefaultType.Yes == security ? "4" : "2"
1038 break; 1042 });
1039 case YesNoDefaultType.Default: // read-only recommended
1040 row.Set(1, "2");
1041 break;
1042 case YesNoDefaultType.Yes: // read-only enforced
1043 row.Set(1, "4");
1044 break;
1045 }
1046 } 1043 }
1047 } 1044 }
1048 1045
@@ -1135,12 +1132,14 @@ namespace WixToolset.Core
1135 1132
1136 if (!this.Core.EncounteredError) 1133 if (!this.Core.EncounteredError)
1137 { 1134 {
1138 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.LockPermissions); 1135 this.Core.AddTuple(new LockPermissionsTuple(sourceLineNumbers)
1139 row.Set(0, objectId); 1136 {
1140 row.Set(1, tableName); 1137 LockObject = objectId,
1141 row.Set(2, domain); 1138 Table = tableName,
1142 row.Set(3, user); 1139 Domain = domain,
1143 row.Set(4, permission); 1140 User = user,
1141 Permission = permission
1142 });
1144 } 1143 }
1145 } 1144 }
1146 1145
@@ -1230,295 +1229,13 @@ namespace WixToolset.Core
1230 1229
1231 if (!this.Core.EncounteredError) 1230 if (!this.Core.EncounteredError)
1232 { 1231 {
1233 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiLockPermissionsEx, id); 1232 this.Core.AddTuple(new MsiLockPermissionsExTuple(sourceLineNumbers, id)
1234 row.Set(1, objectId);
1235 row.Set(2, tableName);
1236 row.Set(3, sddl);
1237 row.Set(4, condition);
1238 }
1239 }
1240
1241 /// <summary>
1242 /// Parses a product element.
1243 /// </summary>
1244 /// <param name="node">Element to parse.</param>
1245 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
1246 private void ParseProductElement(XElement node)
1247 {
1248 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
1249 var codepage = 65001;
1250 string productCode = "*";
1251 string upgradeCode = null;
1252 string manufacturer = null;
1253 string version = null;
1254 string symbols = null;
1255
1256 this.activeName = null;
1257 this.activeLanguage = null;
1258
1259 foreach (var attrib in node.Attributes())
1260 {
1261 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
1262 {
1263 switch (attrib.Name.LocalName)
1264 {
1265 case "Id":
1266 productCode = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, true);
1267 break;
1268 case "Codepage":
1269 codepage = this.Core.GetAttributeCodePageValue(sourceLineNumbers, attrib);
1270 break;
1271 case "Language":
1272 this.activeLanguage = this.Core.GetAttributeLocalizableIntegerValue(sourceLineNumbers, attrib, 0, Int16.MaxValue);
1273 break;
1274 case "Manufacturer":
1275 manufacturer = this.Core.GetAttributeValue(sourceLineNumbers, attrib, EmptyRule.MustHaveNonWhitespaceCharacters);
1276 if ("PUT-COMPANY-NAME-HERE" == manufacturer)
1277 {
1278 this.Core.Write(WarningMessages.PlaceholderValue(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, manufacturer));
1279 }
1280 break;
1281 case "Name":
1282 this.activeName = this.Core.GetAttributeValue(sourceLineNumbers, attrib, EmptyRule.MustHaveNonWhitespaceCharacters);
1283 if ("PUT-PRODUCT-NAME-HERE" == this.activeName)
1284 {
1285 this.Core.Write(WarningMessages.PlaceholderValue(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, this.activeName));
1286 }
1287 break;
1288 case "UpgradeCode":
1289 upgradeCode = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false);
1290 break;
1291 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").
1292 var verifiedVersion = this.Core.GetAttributeVersionValue(sourceLineNumbers, attrib);
1293 if (!String.IsNullOrEmpty(verifiedVersion))
1294 {
1295 version = attrib.Value;
1296 }
1297 break;
1298 default:
1299 this.Core.UnexpectedAttribute(node, attrib);
1300 break;
1301 }
1302 }
1303 else
1304 {
1305 this.Core.ParseExtensionAttribute(node, attrib);
1306 }
1307 }
1308
1309 if (null == productCode)
1310 {
1311 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
1312 }
1313
1314 if (null == this.activeLanguage)
1315 {
1316 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Language"));
1317 }
1318
1319 if (null == manufacturer)
1320 {
1321 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Manufacturer"));
1322 }
1323
1324 if (null == this.activeName)
1325 {
1326 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Name"));
1327 }
1328
1329 if (null == upgradeCode)
1330 {
1331 this.Core.Write(WarningMessages.MissingUpgradeCode(sourceLineNumbers));
1332 }
1333
1334 if (null == version)
1335 {
1336 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Version"));
1337 }
1338 else if (!CompilerCore.IsValidProductVersion(version))
1339 {
1340 this.Core.Write(ErrorMessages.InvalidProductVersion(sourceLineNumbers, version));
1341 }
1342
1343 if (this.Core.EncounteredError)
1344 {
1345 return;
1346 }
1347
1348 try
1349 {
1350 this.compilingProduct = true;
1351 this.Core.CreateActiveSection(productCode, SectionType.Product, codepage, this.Context.CompilationId);
1352
1353 this.AddProperty(sourceLineNumbers, new Identifier("Manufacturer", AccessModifier.Public), manufacturer, false, false, false, true);
1354 this.AddProperty(sourceLineNumbers, new Identifier("ProductCode", AccessModifier.Public), productCode, false, false, false, true);
1355 this.AddProperty(sourceLineNumbers, new Identifier("ProductLanguage", AccessModifier.Public), this.activeLanguage, false, false, false, true);
1356 this.AddProperty(sourceLineNumbers, new Identifier("ProductName", AccessModifier.Public), this.activeName, false, false, false, true);
1357 this.AddProperty(sourceLineNumbers, new Identifier("ProductVersion", AccessModifier.Public), version, false, false, false, true);
1358 if (null != upgradeCode)
1359 {
1360 this.AddProperty(sourceLineNumbers, new Identifier("UpgradeCode", AccessModifier.Public), upgradeCode, false, false, false, true);
1361 }
1362
1363 var contextValues = new Dictionary<string, string>
1364 {
1365 ["ProductLanguage"] = this.activeLanguage,
1366 ["ProductVersion"] = version,
1367 ["UpgradeCode"] = upgradeCode
1368 };
1369
1370 var featureDisplay = 0;
1371 foreach (var child in node.Elements())
1372 {
1373 if (CompilerCore.WixNamespace == child.Name.Namespace)
1374 {
1375 switch (child.Name.LocalName)
1376 {
1377 case "_locDefinition":
1378 break;
1379 case "AdminExecuteSequence":
1380 case "AdminUISequence":
1381 case "AdvertiseExecuteSequence":
1382 case "InstallExecuteSequence":
1383 case "InstallUISequence":
1384 this.ParseSequenceElement(child, child.Name.LocalName);
1385 break;
1386 case "AppId":
1387 this.ParseAppIdElement(child, null, YesNoType.Yes, null, null, null);
1388 break;
1389 case "Binary":
1390 this.ParseBinaryElement(child);
1391 break;
1392 case "ComplianceCheck":
1393 this.ParseComplianceCheckElement(child);
1394 break;
1395 case "Component":
1396 this.ParseComponentElement(child, ComplexReferenceParentType.Unknown, null, null, CompilerConstants.IntegerNotSet, null, null);
1397 break;
1398 case "ComponentGroup":
1399 this.ParseComponentGroupElement(child, ComplexReferenceParentType.Unknown, null);
1400 break;
1401 case "Condition":
1402 this.ParseConditionElement(child, node.Name.LocalName, null, null);
1403 break;
1404 case "CustomAction":
1405 this.ParseCustomActionElement(child);
1406 break;
1407 case "CustomActionRef":
1408 this.ParseSimpleRefElement(child, "CustomAction");
1409 break;
1410 case "CustomTable":
1411 this.ParseCustomTableElement(child);
1412 break;
1413 case "Directory":
1414 this.ParseDirectoryElement(child, null, CompilerConstants.IntegerNotSet, String.Empty);
1415 break;
1416 case "DirectoryRef":
1417 this.ParseDirectoryRefElement(child);
1418 break;
1419 case "EmbeddedChainer":
1420 this.ParseEmbeddedChainerElement(child);
1421 break;
1422 case "EmbeddedChainerRef":
1423 this.ParseSimpleRefElement(child, "MsiEmbeddedChainer");
1424 break;
1425 case "EnsureTable":
1426 this.ParseEnsureTableElement(child);
1427 break;
1428 case "Feature":
1429 this.ParseFeatureElement(child, ComplexReferenceParentType.Product, productCode, ref featureDisplay);
1430 break;
1431 case "FeatureRef":
1432 this.ParseFeatureRefElement(child, ComplexReferenceParentType.Product, productCode);
1433 break;
1434 case "FeatureGroupRef":
1435 this.ParseFeatureGroupRefElement(child, ComplexReferenceParentType.Product, productCode);
1436 break;
1437 case "Icon":
1438 this.ParseIconElement(child);
1439 break;
1440 case "InstanceTransforms":
1441 this.ParseInstanceTransformsElement(child);
1442 break;
1443 case "MajorUpgrade":
1444 this.ParseMajorUpgradeElement(child, contextValues);
1445 break;
1446 case "Media":
1447 this.ParseMediaElement(child, null);
1448 break;
1449 case "MediaTemplate":
1450 this.ParseMediaTemplateElement(child, null);
1451 break;
1452 case "Package":
1453 this.ParsePackageElement(child, manufacturer, null);
1454 break;
1455 case "PackageCertificates":
1456 case "PatchCertificates":
1457 this.ParseCertificatesElement(child);
1458 break;
1459 case "Property":
1460 this.ParsePropertyElement(child);
1461 break;
1462 case "PropertyRef":
1463 this.ParseSimpleRefElement(child, "Property");
1464 break;
1465 case "SetDirectory":
1466 this.ParseSetDirectoryElement(child);
1467 break;
1468 case "SetProperty":
1469 this.ParseSetPropertyElement(child);
1470 break;
1471 case "SFPCatalog":
1472 string parentName = null;
1473 this.ParseSFPCatalogElement(child, ref parentName);
1474 break;
1475 case "SymbolPath":
1476 if (null != symbols)
1477 {
1478 symbols += ";" + this.ParseSymbolPathElement(child);
1479 }
1480 else
1481 {
1482 symbols = this.ParseSymbolPathElement(child);
1483 }
1484 break;
1485 case "UI":
1486 this.ParseUIElement(child);
1487 break;
1488 case "UIRef":
1489 this.ParseSimpleRefElement(child, "WixUI");
1490 break;
1491 case "Upgrade":
1492 this.ParseUpgradeElement(child);
1493 break;
1494 case "WixVariable":
1495 this.ParseWixVariableElement(child);
1496 break;
1497 default:
1498 this.Core.UnexpectedElement(node, child);
1499 break;
1500 }
1501 }
1502 else
1503 {
1504 this.Core.ParseExtensionElement(node, child);
1505 }
1506 }
1507
1508 if (!this.Core.EncounteredError)
1509 { 1233 {
1510 if (null != symbols) 1234 LockObject = objectId,
1511 { 1235 Table = tableName,
1512 var symbolRow = (WixDeltaPatchSymbolPathsTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixDeltaPatchSymbolPaths); 1236 SDDLText =sddl,
1513 symbolRow.Id = productCode; 1237 Condition = condition
1514 symbolRow.Type = SymbolPathType.Product; 1238 });
1515 symbolRow.SymbolPaths = symbols;
1516 }
1517 }
1518 }
1519 finally
1520 {
1521 this.compilingProduct = false;
1522 } 1239 }
1523 } 1240 }
1524 1241
@@ -1644,22 +1361,27 @@ namespace WixToolset.Core
1644 { 1361 {
1645 if (!this.Core.EncounteredError) 1362 if (!this.Core.EncounteredError)
1646 { 1363 {
1647 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ProgId); 1364 var tuple = new ProgIdTuple(sourceLineNumbers, new Identifier(AccessModifier.Public, progId))
1648 row.Set(0, progId); 1365 {
1649 row.Set(1, parent); 1366 ProgId = progId,
1650 row.Set(2, classId); 1367 ProgId_Parent = parent,
1651 row.Set(3, description); 1368 Class_ = classId,
1369 Description = description,
1370 };
1371
1652 if (null != icon) 1372 if (null != icon)
1653 { 1373 {
1654 row.Set(4, icon); 1374 tuple.Icon_ = icon;
1655 this.Core.CreateSimpleReference(sourceLineNumbers, "Icon", icon); 1375 this.Core.CreateSimpleReference(sourceLineNumbers, "Icon", icon);
1656 } 1376 }
1657 1377
1658 if (CompilerConstants.IntegerNotSet != iconIndex) 1378 if (CompilerConstants.IntegerNotSet != iconIndex)
1659 { 1379 {
1660 row.Set(5, iconIndex); 1380 tuple.IconIndex = iconIndex;
1661 } 1381 }
1662 1382
1383 this.Core.AddTuple(tuple);
1384
1663 this.Core.EnsureTable(sourceLineNumbers, "Class"); 1385 this.Core.EnsureTable(sourceLineNumbers, "Class");
1664 } 1386 }
1665 } 1387 }
@@ -1834,7 +1556,7 @@ namespace WixToolset.Core
1834 { 1556 {
1835 if (complianceCheck && !this.Core.EncounteredError) 1557 if (complianceCheck && !this.Core.EncounteredError)
1836 { 1558 {
1837 this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.CCPSearch, new Identifier(sig, AccessModifier.Private)); 1559 this.Core.AddTuple(new CCPSearchTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, sig)));
1838 } 1560 }
1839 1561
1840 this.AddAppSearch(sourceLineNumbers, id, sig); 1562 this.AddAppSearch(sourceLineNumbers, id, sig);
@@ -1863,7 +1585,7 @@ namespace WixToolset.Core
1863 { 1585 {
1864 this.Core.Write(WarningMessages.PropertyModularizationSuppressed(sourceLineNumbers)); 1586 this.Core.Write(WarningMessages.PropertyModularizationSuppressed(sourceLineNumbers));
1865 1587
1866 this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixSuppressModularization, id); 1588 this.Core.AddTuple(new WixSuppressModularizationTuple(sourceLineNumbers, id));
1867 } 1589 }
1868 } 1590 }
1869 1591
@@ -2521,7 +2243,8 @@ namespace WixToolset.Core
2521 Identifier id = null; 2243 Identifier id = null;
2522 string directory = null; 2244 string directory = null;
2523 string name = null; 2245 string name = null;
2524 var on = CompilerConstants.IntegerNotSet; 2246 bool? onInstall = null;
2247 bool? onUninstall = null;
2525 string property = null; 2248 string property = null;
2526 string shortName = null; 2249 string shortName = null;
2527 2250
@@ -2545,16 +2268,14 @@ namespace WixToolset.Core
2545 switch (onValue) 2268 switch (onValue)
2546 { 2269 {
2547 case "install": 2270 case "install":
2548 on = 1; 2271 onInstall = true;
2549 break; 2272 break;
2550 case "uninstall": 2273 case "uninstall":
2551 on = 2; 2274 onUninstall = true;
2552 break; 2275 break;
2553 case "both": 2276 case "both":
2554 on = 3; 2277 onInstall = true;
2555 break; 2278 onUninstall = true;
2556 default:
2557 on = CompilerConstants.IllegalInteger;
2558 break; 2279 break;
2559 } 2280 }
2560 break; 2281 break;
@@ -2599,10 +2320,9 @@ namespace WixToolset.Core
2599 } 2320 }
2600 } 2321 }
2601 2322
2602 if (CompilerConstants.IntegerNotSet == on) 2323 if (!onInstall.HasValue && !onUninstall.HasValue)
2603 { 2324 {
2604 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "On")); 2325 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "On"));
2605 on = CompilerConstants.IllegalInteger;
2606 } 2326 }
2607 2327
2608 if (null != directory && null != property) 2328 if (null != directory && null != property)
@@ -2612,6 +2332,7 @@ namespace WixToolset.Core
2612 2332
2613 if (null == id) 2333 if (null == id)
2614 { 2334 {
2335 var on = (onInstall == true && onUninstall == true) ? 3 : (onUninstall == true) ? 2 : (onInstall == true) ? 1 : 0;
2615 id = this.Core.CreateIdentifier("rmf", directory ?? property ?? parentDirectory, LowercaseOrNull(shortName), LowercaseOrNull(name), on.ToString()); 2336 id = this.Core.CreateIdentifier("rmf", directory ?? property ?? parentDirectory, LowercaseOrNull(shortName), LowercaseOrNull(name), on.ToString());
2616 } 2337 }
2617 2338
@@ -2619,22 +2340,16 @@ namespace WixToolset.Core
2619 2340
2620 if (!this.Core.EncounteredError) 2341 if (!this.Core.EncounteredError)
2621 { 2342 {
2622 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.RemoveFile, id); 2343 var tuple = new RemoveFileTuple(sourceLineNumbers, id)
2623 row.Set(1, componentId);
2624 row.Set(2, this.GetMsiFilenameValue(shortName, name));
2625 if (null != directory)
2626 {
2627 row.Set(3, directory);
2628 }
2629 else if (null != property)
2630 {
2631 row.Set(3, property);
2632 }
2633 else
2634 { 2344 {
2635 row.Set(3, parentDirectory); 2345 Component_ = componentId,
2636 } 2346 FileName = this.GetMsiFilenameValue(shortName, name),
2637 row.Set(4, on); 2347 DirProperty = directory ?? property ?? parentDirectory,
2348 OnInstall = onInstall,
2349 OnUninstall = onUninstall
2350 };
2351
2352 this.Core.AddTuple(tuple);
2638 } 2353 }
2639 } 2354 }
2640 2355
@@ -2649,7 +2364,8 @@ namespace WixToolset.Core
2649 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); 2364 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
2650 Identifier id = null; 2365 Identifier id = null;
2651 string directory = null; 2366 string directory = null;
2652 var on = CompilerConstants.IntegerNotSet; 2367 bool? onInstall = null;
2368 bool? onUninstall = null;
2653 string property = null; 2369 string property = null;
2654 2370
2655 foreach (var attrib in node.Attributes()) 2371 foreach (var attrib in node.Attributes())
@@ -2669,16 +2385,14 @@ namespace WixToolset.Core
2669 switch (onValue) 2385 switch (onValue)
2670 { 2386 {
2671 case "install": 2387 case "install":
2672 on = 1; 2388 onInstall = true;
2673 break; 2389 break;
2674 case "uninstall": 2390 case "uninstall":
2675 on = 2; 2391 onUninstall = true;
2676 break; 2392 break;
2677 case "both": 2393 case "both":
2678 on = 3; 2394 onInstall = true;
2679 break; 2395 onUninstall = true;
2680 default:
2681 on = CompilerConstants.IllegalInteger;
2682 break; 2396 break;
2683 } 2397 }
2684 break; 2398 break;
@@ -2696,10 +2410,9 @@ namespace WixToolset.Core
2696 } 2410 }
2697 } 2411 }
2698 2412
2699 if (CompilerConstants.IntegerNotSet == on) 2413 if (!onInstall.HasValue && !onUninstall.HasValue)
2700 { 2414 {
2701 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "On")); 2415 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "On"));
2702 on = CompilerConstants.IllegalInteger;
2703 } 2416 }
2704 2417
2705 if (null != directory && null != property) 2418 if (null != directory && null != property)
@@ -2709,6 +2422,7 @@ namespace WixToolset.Core
2709 2422
2710 if (null == id) 2423 if (null == id)
2711 { 2424 {
2425 var on = (onInstall == true && onUninstall == true) ? 3 : (onUninstall == true) ? 2 : (onInstall == true) ? 1 : 0;
2712 id = this.Core.CreateIdentifier("rmf", directory ?? property ?? parentDirectory, on.ToString()); 2426 id = this.Core.CreateIdentifier("rmf", directory ?? property ?? parentDirectory, on.ToString());
2713 } 2427 }
2714 2428
@@ -2716,22 +2430,15 @@ namespace WixToolset.Core
2716 2430
2717 if (!this.Core.EncounteredError) 2431 if (!this.Core.EncounteredError)
2718 { 2432 {
2719 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.RemoveFile, id); 2433 var tuple = new RemoveFileTuple(sourceLineNumbers, id)
2720 row.Set(1, componentId);
2721 //row.Set(2, null);
2722 if (null != directory)
2723 { 2434 {
2724 row.Set(3, directory); 2435 Component_ = componentId,
2725 } 2436 DirProperty = directory ?? property ?? parentDirectory,
2726 else if (null != property) 2437 OnInstall = onInstall,
2727 { 2438 OnUninstall = onUninstall
2728 row.Set(3, property); 2439 };
2729 } 2440
2730 else 2441 this.Core.AddTuple(tuple);
2731 {
2732 row.Set(3, parentDirectory);
2733 }
2734 row.Set(4, on);
2735 } 2442 }
2736 } 2443 }
2737 2444
@@ -2796,11 +2503,13 @@ namespace WixToolset.Core
2796 2503
2797 if (!this.Core.EncounteredError) 2504 if (!this.Core.EncounteredError)
2798 { 2505 {
2799 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ReserveCost, id); 2506 this.Core.AddTuple(new ReserveCostTuple(sourceLineNumbers, id)
2800 row.Set(1, componentId); 2507 {
2801 row.Set(2, directoryId); 2508 Component_ = componentId,
2802 row.Set(3, runLocal); 2509 ReserveFolder = directoryId,
2803 row.Set(4, runFromSource); 2510 ReserveLocal = runLocal,
2511 ReserveSource = runFromSource
2512 });
2804 } 2513 }
2805 } 2514 }
2806 2515
@@ -2809,14 +2518,8 @@ namespace WixToolset.Core
2809 /// </summary> 2518 /// </summary>
2810 /// <param name="node">Element to parse.</param> 2519 /// <param name="node">Element to parse.</param>
2811 /// <param name="sequenceTable">Name of sequence table.</param> 2520 /// <param name="sequenceTable">Name of sequence table.</param>
2812 private void ParseSequenceElement(XElement node, string sequenceTable) 2521 private void ParseSequenceElement(XElement node, SequenceTable sequenceTable)
2813 { 2522 {
2814 // use the proper table name internally
2815 if ("AdvertiseExecuteSequence" == sequenceTable)
2816 {
2817 sequenceTable = "AdvtExecuteSequence";
2818 }
2819
2820 // Parse each action in the sequence. 2523 // Parse each action in the sequence.
2821 foreach (var child in node.Elements()) 2524 foreach (var child in node.Elements())
2822 { 2525 {
@@ -2855,7 +2558,7 @@ namespace WixToolset.Core
2855 if (customAction || showDialog || specialAction || specialStandardAction) 2558 if (customAction || showDialog || specialAction || specialStandardAction)
2856 { 2559 {
2857 afterAction = this.Core.GetAttributeIdentifierValue(childSourceLineNumbers, attrib); 2560 afterAction = this.Core.GetAttributeIdentifierValue(childSourceLineNumbers, attrib);
2858 this.Core.CreateSimpleReference(childSourceLineNumbers, "WixAction", sequenceTable, afterAction); 2561 this.Core.CreateSimpleReference(childSourceLineNumbers, "WixAction", sequenceTable.ToString(), afterAction);
2859 } 2562 }
2860 else 2563 else
2861 { 2564 {
@@ -2866,7 +2569,7 @@ namespace WixToolset.Core
2866 if (customAction || showDialog || specialAction || specialStandardAction) 2569 if (customAction || showDialog || specialAction || specialStandardAction)
2867 { 2570 {
2868 beforeAction = this.Core.GetAttributeIdentifierValue(childSourceLineNumbers, attrib); 2571 beforeAction = this.Core.GetAttributeIdentifierValue(childSourceLineNumbers, attrib);
2869 this.Core.CreateSimpleReference(childSourceLineNumbers, "WixAction", sequenceTable, beforeAction); 2572 this.Core.CreateSimpleReference(childSourceLineNumbers, "WixAction", sequenceTable.ToString(), beforeAction);
2870 } 2573 }
2871 else 2574 else
2872 { 2575 {
@@ -2995,23 +2698,30 @@ namespace WixToolset.Core
2995 { 2698 {
2996 if (suppress) 2699 if (suppress)
2997 { 2700 {
2998 var row = this.Core.CreateRow(childSourceLineNumbers, TupleDefinitionType.WixSuppressAction, new Identifier(AccessModifier.Public, sequenceTable, actionName)); 2701 this.Core.AddTuple(new WixSuppressActionTuple(childSourceLineNumbers, new Identifier(AccessModifier.Public, sequenceTable, actionName))
2999 row.Set(0, sequenceTable); 2702 {
3000 row.Set(1, actionName); 2703 SequenceTable = sequenceTable,
2704 Action = actionName
2705 });
3001 } 2706 }
3002 else 2707 else
3003 { 2708 {
3004 var row = this.Core.CreateRow(childSourceLineNumbers, TupleDefinitionType.WixAction, new Identifier(AccessModifier.Public, sequenceTable, actionName)); 2709 var tuple = new WixActionTuple(childSourceLineNumbers, new Identifier(AccessModifier.Public, sequenceTable, actionName))
3005 row.Set(0, sequenceTable); 2710 {
3006 row.Set(1, actionName); 2711 SequenceTable = sequenceTable,
3007 row.Set(2, condition); 2712 Action = actionName,
2713 Condition = condition,
2714 Before = beforeAction,
2715 After = afterAction,
2716 Overridable = overridable,
2717 };
2718
3008 if (CompilerConstants.IntegerNotSet != sequence) 2719 if (CompilerConstants.IntegerNotSet != sequence)
3009 { 2720 {
3010 row.Set(3, sequence); 2721 tuple.Sequence = sequence;
3011 } 2722 }
3012 row.Set(4, beforeAction); 2723
3013 row.Set(5, afterAction); 2724 this.Core.AddTuple(tuple);
3014 row.Set(6, overridable ? 1 : 0);
3015 } 2725 }
3016 } 2726 }
3017 } 2727 }
@@ -3305,7 +3015,7 @@ namespace WixToolset.Core
3305 { 3015 {
3306 if (!String.IsNullOrEmpty(delayedAutoStart)) 3016 if (!String.IsNullOrEmpty(delayedAutoStart))
3307 { 3017 {
3308 var tuple = new MsiServiceConfigTuple(sourceLineNumbers, new Identifier(String.Concat(id.Id, ".DS"), id.Access)) 3018 var tuple = new MsiServiceConfigTuple(sourceLineNumbers, new Identifier(id.Access, String.Concat(id.Id, ".DS")))
3309 { 3019 {
3310 Name = name, 3020 Name = name,
3311 OnInstall = install, 3021 OnInstall = install,
@@ -3327,7 +3037,7 @@ namespace WixToolset.Core
3327 3037
3328 if (!String.IsNullOrEmpty(failureActionsWhen)) 3038 if (!String.IsNullOrEmpty(failureActionsWhen))
3329 { 3039 {
3330 var tuple = new MsiServiceConfigTuple(sourceLineNumbers, new Identifier(String.Concat(id.Id, ".FA"), id.Access)) 3040 var tuple = new MsiServiceConfigTuple(sourceLineNumbers, new Identifier(id.Access, String.Concat(id.Id, ".FA")))
3331 { 3041 {
3332 Name = name, 3042 Name = name,
3333 OnInstall = install, 3043 OnInstall = install,
@@ -3349,7 +3059,7 @@ namespace WixToolset.Core
3349 3059
3350 if (!String.IsNullOrEmpty(sid)) 3060 if (!String.IsNullOrEmpty(sid))
3351 { 3061 {
3352 var tuple = new MsiServiceConfigTuple(sourceLineNumbers, new Identifier(String.Concat(id.Id, ".SS"), id.Access)) 3062 var tuple = new MsiServiceConfigTuple(sourceLineNumbers, new Identifier(id.Access, String.Concat(id.Id, ".SS")))
3353 { 3063 {
3354 Name = name, 3064 Name = name,
3355 OnInstall = install, 3065 OnInstall = install,
@@ -3371,7 +3081,7 @@ namespace WixToolset.Core
3371 3081
3372 if (!String.IsNullOrEmpty(requiredPrivileges)) 3082 if (!String.IsNullOrEmpty(requiredPrivileges))
3373 { 3083 {
3374 var tuple = new MsiServiceConfigTuple(sourceLineNumbers, new Identifier(String.Concat(id.Id, ".RP"), id.Access)) 3084 var tuple = new MsiServiceConfigTuple(sourceLineNumbers, new Identifier(id.Access, String.Concat(id.Id, ".RP")))
3375 { 3085 {
3376 Name = name, 3086 Name = name,
3377 OnInstall = install, 3087 OnInstall = install,
@@ -3393,7 +3103,7 @@ namespace WixToolset.Core
3393 3103
3394 if (!String.IsNullOrEmpty(preShutdownDelay)) 3104 if (!String.IsNullOrEmpty(preShutdownDelay))
3395 { 3105 {
3396 var tuple = new MsiServiceConfigTuple(sourceLineNumbers, new Identifier(String.Concat(id.Id, ".PD"), id.Access)) 3106 var tuple = new MsiServiceConfigTuple(sourceLineNumbers, new Identifier(id.Access, String.Concat(id.Id, ".PD")))
3397 { 3107 {
3398 Name = name, 3108 Name = name,
3399 OnInstall = install, 3109 OnInstall = install,
@@ -4320,9 +4030,11 @@ namespace WixToolset.Core
4320 4030
4321 if (!this.Core.EncounteredError) 4031 if (!this.Core.EncounteredError)
4322 { 4032 {
4323 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.FileSFPCatalog); 4033 this.Core.AddTuple(new FileSFPCatalogTuple(sourceLineNumbers)
4324 row.Set(0, id); 4034 {
4325 row.Set(1, parentSFPCatalog); 4035 File_ = id,
4036 SFPCatalog_ = parentSFPCatalog
4037 });
4326 } 4038 }
4327 } 4039 }
4328 4040
@@ -4411,10 +4123,12 @@ namespace WixToolset.Core
4411 4123
4412 if (!this.Core.EncounteredError) 4124 if (!this.Core.EncounteredError)
4413 { 4125 {
4414 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.SFPCatalog); 4126 this.Core.AddTuple(new SFPCatalogTuple(sourceLineNumbers)
4415 row.Set(0, name); 4127 {
4416 row.Set(1, sourceFile); 4128 SFPCatalog = name,
4417 row.Set(2, dependency); 4129 Catalog = sourceFile,
4130 Dependency = dependency
4131 });
4418 } 4132 }
4419 } 4133 }
4420 4134
@@ -4827,10 +4541,12 @@ namespace WixToolset.Core
4827 4541
4828 if (!this.Core.EncounteredError) 4542 if (!this.Core.EncounteredError)
4829 { 4543 {
4830 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiShortcutProperty, id); 4544 this.Core.AddTuple(new MsiShortcutPropertyTuple(sourceLineNumbers, id)
4831 row.Set(1, shortcutId); 4545 {
4832 row.Set(2, key); 4546 Shortcut_ = shortcutId,
4833 row.Set(3, value); 4547 PropertyKey = key,
4548 PropVariantValue = value
4549 });
4834 } 4550 }
4835 } 4551 }
4836 4552
@@ -5022,21 +4738,27 @@ namespace WixToolset.Core
5022 4738
5023 if (!this.Core.EncounteredError) 4739 if (!this.Core.EncounteredError)
5024 { 4740 {
5025 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.TypeLib); 4741 var tuple = new TypeLibTuple(sourceLineNumbers)
5026 row.Set(0, id); 4742 {
5027 row.Set(1, language); 4743 LibId = id,
5028 row.Set(2, componentId); 4744 Language = language,
4745 Component_ = componentId,
4746 Description = description,
4747 Directory_ = helpDirectory,
4748 Feature_ = Guid.Empty.ToString("B")
4749 };
4750
5029 if (CompilerConstants.IntegerNotSet != majorVersion || CompilerConstants.IntegerNotSet != minorVersion) 4751 if (CompilerConstants.IntegerNotSet != majorVersion || CompilerConstants.IntegerNotSet != minorVersion)
5030 { 4752 {
5031 row.Set(3, (CompilerConstants.IntegerNotSet != majorVersion ? majorVersion * 256 : 0) + (CompilerConstants.IntegerNotSet != minorVersion ? minorVersion : 0)); 4753 tuple.Version = (CompilerConstants.IntegerNotSet != majorVersion ? majorVersion * 256 : 0) + (CompilerConstants.IntegerNotSet != minorVersion ? minorVersion : 0);
5032 } 4754 }
5033 row.Set(4, description); 4755
5034 row.Set(5, helpDirectory);
5035 row.Set(6, Guid.Empty.ToString("B"));
5036 if (CompilerConstants.IntegerNotSet != cost) 4756 if (CompilerConstants.IntegerNotSet != cost)
5037 { 4757 {
5038 row.Set(7, cost); 4758 tuple.Cost = cost;
5039 } 4759 }
4760
4761 this.Core.AddTuple(tuple);
5040 } 4762 }
5041 } 4763 }
5042 else if (YesNoType.No == advertise) 4764 else if (YesNoType.No == advertise)
@@ -5250,7 +4972,7 @@ namespace WixToolset.Core
5250 this.Core.AddTuple(tuple); 4972 this.Core.AddTuple(tuple);
5251 4973
5252 // Ensure the action property is secure. 4974 // Ensure the action property is secure.
5253 this.AddWixPropertyRow(sourceLineNumbers, new Identifier(actionProperty, AccessModifier.Private), false, true, false); 4975 this.AddWixPropertyRow(sourceLineNumbers, new Identifier(AccessModifier.Private, actionProperty), false, true, false);
5254 4976
5255 // Ensure that RemoveExistingProducts is authored in InstallExecuteSequence 4977 // Ensure that RemoveExistingProducts is authored in InstallExecuteSequence
5256 // if at least one row in Upgrade table lacks the OnlyDetect attribute. 4978 // if at least one row in Upgrade table lacks the OnlyDetect attribute.
@@ -5361,15 +5083,20 @@ namespace WixToolset.Core
5361 5083
5362 if (!this.Core.EncounteredError) 5084 if (!this.Core.EncounteredError)
5363 { 5085 {
5364 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Verb); 5086 var tuple = new VerbTuple(sourceLineNumbers)
5365 row.Set(0, extension); 5087 {
5366 row.Set(1, id); 5088 Extension_ = extension,
5089 Verb = id,
5090 Command = command,
5091 Argument = argument,
5092 };
5093
5367 if (CompilerConstants.IntegerNotSet != sequence) 5094 if (CompilerConstants.IntegerNotSet != sequence)
5368 { 5095 {
5369 row.Set(2, sequence); 5096 tuple.Sequence = sequence;
5370 } 5097 }
5371 row.Set(3, command); 5098
5372 row.Set(4, argument); 5099 this.Core.AddTuple(tuple);
5373 } 5100 }
5374 } 5101 }
5375 else if (YesNoType.No == advertise) 5102 else if (YesNoType.No == advertise)
@@ -5414,76 +5141,6 @@ namespace WixToolset.Core
5414 } 5141 }
5415 5142
5416 /// <summary> 5143 /// <summary>
5417 /// Parses a Wix element.
5418 /// </summary>
5419 /// <param name="node">Element to parse.</param>
5420 private void ParseWixElement(XElement node)
5421 {
5422 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
5423 string requiredVersion = null;
5424
5425 foreach (var attrib in node.Attributes())
5426 {
5427 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
5428 {
5429 switch (attrib.Name.LocalName)
5430 {
5431 case "RequiredVersion":
5432 requiredVersion = this.Core.GetAttributeVersionValue(sourceLineNumbers, attrib);
5433 break;
5434 default:
5435 this.Core.UnexpectedAttribute(node, attrib);
5436 break;
5437 }
5438 }
5439 else
5440 {
5441 this.Core.ParseExtensionAttribute(node, attrib);
5442 }
5443 }
5444
5445 if (null != requiredVersion)
5446 {
5447 this.Core.VerifyRequiredVersion(sourceLineNumbers, requiredVersion);
5448 }
5449
5450 foreach (var child in node.Elements())
5451 {
5452 if (CompilerCore.WixNamespace == child.Name.Namespace)
5453 {
5454 switch (child.Name.LocalName)
5455 {
5456 case "Bundle":
5457 this.ParseBundleElement(child);
5458 break;
5459 case "Fragment":
5460 this.ParseFragmentElement(child);
5461 break;
5462 case "Module":
5463 this.ParseModuleElement(child);
5464 break;
5465 case "PatchCreation":
5466 this.ParsePatchCreationElement(child);
5467 break;
5468 case "Product":
5469 this.ParseProductElement(child);
5470 break;
5471 case "Patch":
5472 this.ParsePatchElement(child);
5473 break;
5474 default:
5475 this.Core.UnexpectedElement(node, child);
5476 break;
5477 }
5478 }
5479 else
5480 {
5481 this.Core.ParseExtensionElement(node, child);
5482 }
5483 }
5484 }
5485
5486 /// <summary>
5487 /// Parses a WixVariable element. 5144 /// Parses a WixVariable element.
5488 /// </summary> 5145 /// </summary>
5489 /// <param name="node">Element to parse.</param> 5146 /// <param name="node">Element to parse.</param>
@@ -5534,9 +5191,11 @@ namespace WixToolset.Core
5534 5191
5535 if (!this.Core.EncounteredError) 5192 if (!this.Core.EncounteredError)
5536 { 5193 {
5537 var wixVariableRow = (WixVariableTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixVariable, id); 5194 this.Core.AddTuple(new WixVariableTuple(sourceLineNumbers, id)
5538 wixVariableRow.Value = value; 5195 {
5539 wixVariableRow.Overridable = overridable; 5196 Value = value,
5197 Overridable = overridable
5198 });
5540 } 5199 }
5541 } 5200 }
5542 5201
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
17 /// </summary> 17 /// </summary>
18 internal partial class Compiler : ICompiler 18 internal partial class Compiler : ICompiler
19 { 19 {
20 public const string BurnUXContainerId = "WixUXContainer"; 20 public static readonly Identifier BurnUXContainerId = new Identifier(AccessModifier.Private, "WixUXContainer");
21 public const string BurnDefaultAttachedContainerId = "WixAttachedContainer"; 21 public static readonly Identifier BurnDefaultAttachedContainerId = new Identifier(AccessModifier.Private, "WixAttachedContainer");
22 22 public static readonly Identifier BundleLayoutOnlyPayloads = new Identifier(AccessModifier.Private, "BundleLayoutOnlyPayloads");
23
23 // The following constants must stay in sync with src\burn\engine\core.h 24 // The following constants must stay in sync with src\burn\engine\core.h
24 private const string BURN_BUNDLE_NAME = "WixBundleName"; 25 private const string BURN_BUNDLE_NAME = "WixBundleName";
25 private const string BURN_BUNDLE_ORIGINAL_SOURCE = "WixBundleOriginalSource"; 26 private const string BURN_BUNDLE_ORIGINAL_SOURCE = "WixBundleOriginalSource";
@@ -88,10 +89,14 @@ namespace WixToolset.Core
88 89
89 if (!this.Core.EncounteredError) 90 if (!this.Core.EncounteredError)
90 { 91 {
91 var wixApprovedExeForElevationRow = (WixApprovedExeForElevationTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixApprovedExeForElevation, id); 92 var tuple = new WixApprovedExeForElevationTuple(sourceLineNumbers, id)
92 wixApprovedExeForElevationRow.Key = key; 93 {
93 wixApprovedExeForElevationRow.Value = valueName; 94 Key = key,
94 wixApprovedExeForElevationRow.Attributes = (int)attributes; 95 Value = valueName,
96 Attributes = attributes
97 };
98
99 this.Core.AddTuple(tuple);
95 } 100 }
96 } 101 }
97 102
@@ -311,10 +316,10 @@ namespace WixToolset.Core
311 logSeen = true; 316 logSeen = true;
312 break; 317 break;
313 case "PayloadGroup": 318 case "PayloadGroup":
314 this.ParsePayloadGroupElement(child, ComplexReferenceParentType.Layout, "BundleLayoutOnlyPayloads"); 319 this.ParsePayloadGroupElement(child, ComplexReferenceParentType.Layout, Compiler.BundleLayoutOnlyPayloads);
315 break; 320 break;
316 case "PayloadGroupRef": 321 case "PayloadGroupRef":
317 this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Layout, "BundleLayoutOnlyPayloads", ComplexReferenceChildType.Unknown, null); 322 this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Layout, Compiler.BundleLayoutOnlyPayloads, ComplexReferenceChildType.Unknown, null);
318 break; 323 break;
319 case "RelatedBundle": 324 case "RelatedBundle":
320 this.ParseRelatedBundleElement(child); 325 this.ParseRelatedBundleElement(child);
@@ -348,72 +353,75 @@ namespace WixToolset.Core
348 { 353 {
349 if (null != upgradeCode) 354 if (null != upgradeCode)
350 { 355 {
351 var tuple = new WixRelatedBundleTuple(sourceLineNumbers) 356 this.Core.AddTuple(new WixRelatedBundleTuple(sourceLineNumbers)
352 { 357 {
353 BundleId = upgradeCode, 358 BundleId = upgradeCode,
354 Action = RelatedBundleActionType.Upgrade, 359 Action = RelatedBundleActionType.Upgrade,
355 }; 360 });
356
357 this.Core.AddTuple(tuple);
358 } 361 }
359 362
360 var containerRow = (WixBundleContainerTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleContainer); 363 this.Core.AddTuple(new WixBundleContainerTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, Compiler.BurnDefaultAttachedContainerId))
361 containerRow.WixBundleContainer = Compiler.BurnDefaultAttachedContainerId; 364 {
362 containerRow.Name = "bundle-attached.cab"; 365 Name = "bundle-attached.cab",
363 containerRow.Type = ContainerType.Attached; 366 Type = ContainerType.Attached
367 });
364 368
365 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundle); 369 var bundleTuple = this.Core.CreateTuple(sourceLineNumbers, TupleDefinitionType.WixBundle);
366 row.Set(0, version); 370 bundleTuple.Set(0, version);
367 row.Set(1, copyright); 371 bundleTuple.Set(1, copyright);
368 row.Set(2, name); 372 bundleTuple.Set(2, name);
369 row.Set(3, aboutUrl); 373 bundleTuple.Set(3, aboutUrl);
370 if (-1 != disableModify) 374 if (-1 != disableModify)
371 { 375 {
372 row.Set(4, disableModify); 376 bundleTuple.Set(4, disableModify);
373 } 377 }
374 if (YesNoType.NotSet != disableRemove) 378 if (YesNoType.NotSet != disableRemove)
375 { 379 {
376 row.Set(5, (YesNoType.Yes == disableRemove) ? 1 : 0); 380 bundleTuple.Set(5, (YesNoType.Yes == disableRemove) ? 1 : 0);
377 } 381 }
378 // row.Set(6] - (deprecated) "disable repair" 382 // row.Set(6] - (deprecated) "disable repair"
379 row.Set(7, helpTelephone); 383 bundleTuple.Set(7, helpTelephone);
380 row.Set(8, helpUrl); 384 bundleTuple.Set(8, helpUrl);
381 row.Set(9, manufacturer); 385 bundleTuple.Set(9, manufacturer);
382 row.Set(10, updateUrl); 386 bundleTuple.Set(10, updateUrl);
383 if (YesNoDefaultType.Default != compressed) 387 if (YesNoDefaultType.Default != compressed)
384 { 388 {
385 row.Set(11, (YesNoDefaultType.Yes == compressed) ? 1 : 0); 389 bundleTuple.Set(11, (YesNoDefaultType.Yes == compressed) ? 1 : 0);
386 } 390 }
387 391
388 row.Set(12, logVariablePrefixAndExtension); 392 bundleTuple.Set(12, logVariablePrefixAndExtension);
389 row.Set(13, iconSourceFile); 393 bundleTuple.Set(13, iconSourceFile);
390 row.Set(14, splashScreenSourceFile); 394 bundleTuple.Set(14, splashScreenSourceFile);
391 row.Set(15, condition); 395 bundleTuple.Set(15, condition);
392 row.Set(16, tag); 396 bundleTuple.Set(16, tag);
393 row.Set(17, this.CurrentPlatform.ToString()); 397 bundleTuple.Set(17, this.CurrentPlatform.ToString());
394 row.Set(18, parentName); 398 bundleTuple.Set(18, parentName);
395 row.Set(19, upgradeCode); 399 bundleTuple.Set(19, upgradeCode);
396 400
397 // Ensure that the bundle stores the well-known persisted values. 401 // Ensure that the bundle stores the well-known persisted values.
398 var bundleNameWellKnownVariable = (WixBundleVariableTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleVariable); 402 this.Core.AddTuple(new WixBundleVariableTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, Compiler.BURN_BUNDLE_NAME))
399 bundleNameWellKnownVariable.WixBundleVariable = Compiler.BURN_BUNDLE_NAME; 403 {
400 bundleNameWellKnownVariable.Hidden = false; 404 Hidden = false,
401 bundleNameWellKnownVariable.Persisted = true; 405 Persisted = true
402 406 });
403 var bundleOriginalSourceWellKnownVariable = (WixBundleVariableTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleVariable); 407
404 bundleOriginalSourceWellKnownVariable.WixBundleVariable = Compiler.BURN_BUNDLE_ORIGINAL_SOURCE; 408 this.Core.AddTuple(new WixBundleVariableTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, Compiler.BURN_BUNDLE_ORIGINAL_SOURCE))
405 bundleOriginalSourceWellKnownVariable.Hidden = false; 409 {
406 bundleOriginalSourceWellKnownVariable.Persisted = true; 410 Hidden = false,
407 411 Persisted = true
408 var bundleOriginalSourceFolderWellKnownVariable = (WixBundleVariableTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleVariable); 412 });
409 bundleOriginalSourceFolderWellKnownVariable.WixBundleVariable = Compiler.BURN_BUNDLE_ORIGINAL_SOURCE_FOLDER; 413
410 bundleOriginalSourceFolderWellKnownVariable.Hidden = false; 414 this.Core.AddTuple(new WixBundleVariableTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, Compiler.BURN_BUNDLE_ORIGINAL_SOURCE_FOLDER))
411 bundleOriginalSourceFolderWellKnownVariable.Persisted = true; 415 {
412 416 Hidden = false,
413 var bundleLastUsedSourceWellKnownVariable = (WixBundleVariableTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleVariable); 417 Persisted = true
414 bundleLastUsedSourceWellKnownVariable.WixBundleVariable = Compiler.BURN_BUNDLE_LAST_USED_SOURCE; 418 });
415 bundleLastUsedSourceWellKnownVariable.Hidden = false; 419
416 bundleLastUsedSourceWellKnownVariable.Persisted = true; 420 this.Core.AddTuple(new WixBundleVariableTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, Compiler.BURN_BUNDLE_LAST_USED_SOURCE))
421 {
422 Hidden = false,
423 Persisted = true
424 });
417 } 425 }
418 } 426 }
419 427
@@ -514,8 +522,10 @@ namespace WixToolset.Core
514 { 522 {
515 this.CreatePayloadRow(sourceLineNumbers, id, Path.GetFileName(sourceFile), sourceFile, null, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, ComplexReferenceChildType.Unknown, null, YesNoDefaultType.Yes, YesNoType.Yes, null, null, null); 523 this.CreatePayloadRow(sourceLineNumbers, id, Path.GetFileName(sourceFile), sourceFile, null, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, ComplexReferenceChildType.Unknown, null, YesNoDefaultType.Yes, YesNoType.Yes, null, null, null);
516 524
517 var wixCatalogRow = (WixBundleCatalogTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleCatalog, id); 525 this.Core.AddTuple(new WixBundleCatalogTuple(sourceLineNumbers, id)
518 wixCatalogRow.Payload_ = id.Id; 526 {
527 Payload_ = id.Id,
528 });
519 } 529 }
520 } 530 }
521 531
@@ -614,10 +624,12 @@ namespace WixToolset.Core
614 624
615 if (!this.Core.EncounteredError) 625 if (!this.Core.EncounteredError)
616 { 626 {
617 var row = (WixBundleContainerTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleContainer, id); 627 this.Core.AddTuple(new WixBundleContainerTuple(sourceLineNumbers, id)
618 row.Name = name; 628 {
619 row.Type = type; 629 Name = name,
620 row.DownloadUrl = downloadUrl; 630 Type = type,
631 DownloadUrl = downloadUrl
632 });
621 } 633 }
622 } 634 }
623 635
@@ -628,12 +640,11 @@ namespace WixToolset.Core
628 private void ParseBootstrapperApplicationElement(XElement node) 640 private void ParseBootstrapperApplicationElement(XElement node)
629 { 641 {
630 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); 642 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
631 string id = null; 643 Identifier previousId = null;
632 string previousId = null;
633 var previousType = ComplexReferenceChildType.Unknown; 644 var previousType = ComplexReferenceChildType.Unknown;
634 645
635 // The BootstrapperApplication element acts like a Payload element so delegate to the "Payload" attribute parsing code to parse and create a Payload entry. 646 // The BootstrapperApplication element acts like a Payload element so delegate to the "Payload" attribute parsing code to parse and create a Payload entry.
636 id = this.ParsePayloadElementContent(node, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, previousType, previousId, false); 647 var id = this.ParsePayloadElementContent(node, ComplexReferenceParentType.Container, Compiler.BurnUXContainerId, previousType, previousId, false);
637 if (null != id) 648 if (null != id)
638 { 649 {
639 previousId = id; 650 previousId = id;
@@ -676,15 +687,15 @@ namespace WixToolset.Core
676 // Add the application as an attached container and if an Id was provided add that too. 687 // Add the application as an attached container and if an Id was provided add that too.
677 if (!this.Core.EncounteredError) 688 if (!this.Core.EncounteredError)
678 { 689 {
679 var containerRow = (WixBundleContainerTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleContainer); 690 this.Core.AddTuple(new WixBundleContainerTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, Compiler.BurnUXContainerId))
680 containerRow.WixBundleContainer = Compiler.BurnUXContainerId; 691 {
681 containerRow.Name = "bundle-ux.cab"; 692 Name = "bundle-ux.cab",
682 containerRow.Type = ContainerType.Attached; 693 Type = ContainerType.Attached
694 });
683 695
684 if (!String.IsNullOrEmpty(id)) 696 if (null != id)
685 { 697 {
686 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBootstrapperApplication); 698 this.Core.AddTuple(new WixBootstrapperApplicationTuple(sourceLineNumbers, id));
687 row.Set(0, id);
688 } 699 }
689 } 700 }
690 } 701 }
@@ -697,7 +708,7 @@ namespace WixToolset.Core
697 { 708 {
698 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); 709 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
699 string id = null; 710 string id = null;
700 string previousId = null; 711 Identifier previousId = null;
701 var previousType = ComplexReferenceChildType.Unknown; 712 var previousType = ComplexReferenceChildType.Unknown;
702 713
703 foreach (var attrib in node.Attributes()) 714 foreach (var attrib in node.Attributes())
@@ -847,12 +858,14 @@ namespace WixToolset.Core
847 858
848 if (!this.Core.EncounteredError) 859 if (!this.Core.EncounteredError)
849 { 860 {
850 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixUpdateRegistration); 861 this.Core.AddTuple(new WixUpdateRegistrationTuple(sourceLineNumbers)
851 row.Set(0, manufacturer); 862 {
852 row.Set(1, department); 863 Manufacturer = manufacturer,
853 row.Set(2, productFamily); 864 Department = department,
854 row.Set(3, name); 865 ProductFamily = productFamily,
855 row.Set(4, classification); 866 Name = name,
867 Classification = classification
868 });
856 } 869 }
857 } 870 }
858 871
@@ -862,7 +875,7 @@ namespace WixToolset.Core
862 /// <param name="node">Element to parse</param> 875 /// <param name="node">Element to parse</param>
863 /// <param name="parentType">ComplexReferenceParentType of parent element. (BA or PayloadGroup)</param> 876 /// <param name="parentType">ComplexReferenceParentType of parent element. (BA or PayloadGroup)</param>
864 /// <param name="parentId">Identifier of parent element.</param> 877 /// <param name="parentId">Identifier of parent element.</param>
865 private string ParsePayloadElement(XElement node, ComplexReferenceParentType parentType, string parentId, ComplexReferenceChildType previousType, string previousId) 878 private Identifier ParsePayloadElement(XElement node, ComplexReferenceParentType parentType, Identifier parentId, ComplexReferenceChildType previousType, Identifier previousId)
866 { 879 {
867 Debug.Assert(ComplexReferenceParentType.PayloadGroup == parentType || ComplexReferenceParentType.Package == parentType || ComplexReferenceParentType.Container == parentType); 880 Debug.Assert(ComplexReferenceParentType.PayloadGroup == parentType || ComplexReferenceParentType.Package == parentType || ComplexReferenceParentType.Container == parentType);
868 Debug.Assert(ComplexReferenceChildType.Unknown == previousType || ComplexReferenceChildType.PayloadGroup == previousType || ComplexReferenceChildType.Payload == previousType); 881 Debug.Assert(ComplexReferenceChildType.Unknown == previousType || ComplexReferenceChildType.PayloadGroup == previousType || ComplexReferenceChildType.Payload == previousType);
@@ -870,7 +883,7 @@ namespace WixToolset.Core
870 var id = this.ParsePayloadElementContent(node, parentType, parentId, previousType, previousId, true); 883 var id = this.ParsePayloadElementContent(node, parentType, parentId, previousType, previousId, true);
871 var context = new Dictionary<string, string> 884 var context = new Dictionary<string, string>
872 { 885 {
873 ["Id"] = id 886 ["Id"] = id.Id
874 }; 887 };
875 888
876 foreach (var child in node.Elements()) 889 foreach (var child in node.Elements())
@@ -899,7 +912,7 @@ namespace WixToolset.Core
899 /// <param name="node">Element to parse</param> 912 /// <param name="node">Element to parse</param>
900 /// <param name="parentType">ComplexReferenceParentType of parent element.</param> 913 /// <param name="parentType">ComplexReferenceParentType of parent element.</param>
901 /// <param name="parentId">Identifier of parent element.</param> 914 /// <param name="parentId">Identifier of parent element.</param>
902 private string ParsePayloadElementContent(XElement node, ComplexReferenceParentType parentType, string parentId, ComplexReferenceChildType previousType, string previousId, bool required) 915 private Identifier ParsePayloadElementContent(XElement node, ComplexReferenceParentType parentType, Identifier parentId, ComplexReferenceChildType previousType, Identifier previousId, bool required)
903 { 916 {
904 Debug.Assert(ComplexReferenceParentType.PayloadGroup == parentType || ComplexReferenceParentType.Package == parentType || ComplexReferenceParentType.Container == parentType); 917 Debug.Assert(ComplexReferenceParentType.PayloadGroup == parentType || ComplexReferenceParentType.Package == parentType || ComplexReferenceParentType.Container == parentType);
905 918
@@ -959,7 +972,7 @@ namespace WixToolset.Core
959 972
960 if (null == id) 973 if (null == id)
961 { 974 {
962 id = this.Core.CreateIdentifier("pay", (null != sourceFile) ? sourceFile.ToUpperInvariant() : String.Empty); 975 id = this.Core.CreateIdentifier("pay", sourceFile?.ToUpperInvariant() ?? String.Empty);
963 } 976 }
964 977
965 // Now that the PayloadId is known, we can parse the extension attributes. 978 // Now that the PayloadId is known, we can parse the extension attributes.
@@ -1022,7 +1035,7 @@ namespace WixToolset.Core
1022 1035
1023 this.CreatePayloadRow(sourceLineNumbers, id, name, sourceFile, downloadUrl, parentType, parentId, previousType, previousId, compressed, enableSignatureVerification, null, null, remotePayload); 1036 this.CreatePayloadRow(sourceLineNumbers, id, name, sourceFile, downloadUrl, parentType, parentId, previousType, previousId, compressed, enableSignatureVerification, null, null, remotePayload);
1024 1037
1025 return id.Id; 1038 return id;
1026 } 1039 }
1027 1040
1028 private RemotePayload ParseRemotePayloadElement(XElement node) 1041 private RemotePayload ParseRemotePayloadElement(XElement node)
@@ -1103,38 +1116,42 @@ namespace WixToolset.Core
1103 /// <param name="parentType">ComplexReferenceParentType of parent element</param> 1116 /// <param name="parentType">ComplexReferenceParentType of parent element</param>
1104 /// <param name="parentId">Identifier of parent element.</param> 1117 /// <param name="parentId">Identifier of parent element.</param>
1105 private WixBundlePayloadTuple CreatePayloadRow(SourceLineNumber sourceLineNumbers, Identifier id, string name, string sourceFile, string downloadUrl, ComplexReferenceParentType parentType, 1118 private WixBundlePayloadTuple CreatePayloadRow(SourceLineNumber sourceLineNumbers, Identifier id, string name, string sourceFile, string downloadUrl, ComplexReferenceParentType parentType,
1106 string parentId, ComplexReferenceChildType previousType, string previousId, YesNoDefaultType compressed, YesNoType enableSignatureVerification, string displayName, string description, 1119 Identifier parentId, ComplexReferenceChildType previousType, Identifier previousId, YesNoDefaultType compressed, YesNoType enableSignatureVerification, string displayName, string description,
1107 RemotePayload remotePayload) 1120 RemotePayload remotePayload)
1108 { 1121 {
1109 WixBundlePayloadTuple row = null; 1122 WixBundlePayloadTuple tuple = null;
1110 1123
1111 if (!this.Core.EncounteredError) 1124 if (!this.Core.EncounteredError)
1112 { 1125 {
1113 row = (WixBundlePayloadTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundlePayload, id); 1126 tuple = new WixBundlePayloadTuple(sourceLineNumbers, id)
1114 row.Name = String.IsNullOrEmpty(name) ? Path.GetFileName(sourceFile) : name; 1127 {
1115 row.SourceFile = sourceFile; 1128 Name = String.IsNullOrEmpty(name) ? Path.GetFileName(sourceFile) : name,
1116 row.DownloadUrl = downloadUrl; 1129 SourceFile = sourceFile,
1117 row.Compressed = compressed; 1130 DownloadUrl = downloadUrl,
1118 row.UnresolvedSourceFile = sourceFile; // duplicate of sourceFile but in a string column so it won't get resolved to a full path during binding. 1131 Compressed = compressed,
1119 row.DisplayName = displayName; 1132 UnresolvedSourceFile = sourceFile, // duplicate of sourceFile but in a string column so it won't get resolved to a full path during binding.
1120 row.Description = description; 1133 DisplayName = displayName,
1121 row.EnableSignatureValidation = (YesNoType.Yes == enableSignatureVerification); 1134 Description = description,
1135 EnableSignatureValidation = (YesNoType.Yes == enableSignatureVerification)
1136 };
1122 1137
1123 if (null != remotePayload) 1138 if (null != remotePayload)
1124 { 1139 {
1125 row.Description = remotePayload.Description; 1140 tuple.Description = remotePayload.Description;
1126 row.DisplayName = remotePayload.ProductName; 1141 tuple.DisplayName = remotePayload.ProductName;
1127 row.Hash = remotePayload.Hash; 1142 tuple.Hash = remotePayload.Hash;
1128 row.PublicKey = remotePayload.CertificatePublicKey; 1143 tuple.PublicKey = remotePayload.CertificatePublicKey;
1129 row.Thumbprint = remotePayload.CertificateThumbprint; 1144 tuple.Thumbprint = remotePayload.CertificateThumbprint;
1130 row.FileSize = remotePayload.Size; 1145 tuple.FileSize = remotePayload.Size;
1131 row.Version = remotePayload.Version; 1146 tuple.Version = remotePayload.Version;
1132 } 1147 }
1133 1148
1134 this.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId, ComplexReferenceChildType.Payload, id.Id, previousType, previousId); 1149 this.Core.AddTuple(tuple);
1150
1151 this.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId.Id, ComplexReferenceChildType.Payload, id.Id, previousType, previousId.Id);
1135 } 1152 }
1136 1153
1137 return row; 1154 return tuple;
1138 } 1155 }
1139 1156
1140 /// <summary> 1157 /// <summary>
@@ -1143,7 +1160,7 @@ namespace WixToolset.Core
1143 /// <param name="node">Element to parse</param> 1160 /// <param name="node">Element to parse</param>
1144 /// <param name="parentType">Optional ComplexReferenceParentType of parent element. (typically another PayloadGroup)</param> 1161 /// <param name="parentType">Optional ComplexReferenceParentType of parent element. (typically another PayloadGroup)</param>
1145 /// <param name="parentId">Identifier of parent element.</param> 1162 /// <param name="parentId">Identifier of parent element.</param>
1146 private void ParsePayloadGroupElement(XElement node, ComplexReferenceParentType parentType, string parentId) 1163 private void ParsePayloadGroupElement(XElement node, ComplexReferenceParentType parentType, Identifier parentId)
1147 { 1164 {
1148 Debug.Assert(ComplexReferenceParentType.Unknown == parentType || ComplexReferenceParentType.Layout == parentType || ComplexReferenceParentType.PayloadGroup == parentType); 1165 Debug.Assert(ComplexReferenceParentType.Unknown == parentType || ComplexReferenceParentType.Layout == parentType || ComplexReferenceParentType.PayloadGroup == parentType);
1149 1166
@@ -1177,7 +1194,7 @@ namespace WixToolset.Core
1177 } 1194 }
1178 1195
1179 var previousType = ComplexReferenceChildType.Unknown; 1196 var previousType = ComplexReferenceChildType.Unknown;
1180 string previousId = null; 1197 Identifier previousId = null;
1181 foreach (var child in node.Elements()) 1198 foreach (var child in node.Elements())
1182 { 1199 {
1183 if (CompilerCore.WixNamespace == child.Name.Namespace) 1200 if (CompilerCore.WixNamespace == child.Name.Namespace)
@@ -1185,11 +1202,11 @@ namespace WixToolset.Core
1185 switch (child.Name.LocalName) 1202 switch (child.Name.LocalName)
1186 { 1203 {
1187 case "Payload": 1204 case "Payload":
1188 previousId = this.ParsePayloadElement(child, ComplexReferenceParentType.PayloadGroup, id.Id, previousType, previousId); 1205 previousId = this.ParsePayloadElement(child, ComplexReferenceParentType.PayloadGroup, id, previousType, previousId);
1189 previousType = ComplexReferenceChildType.Payload; 1206 previousType = ComplexReferenceChildType.Payload;
1190 break; 1207 break;
1191 case "PayloadGroupRef": 1208 case "PayloadGroupRef":
1192 previousId = this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.PayloadGroup, id.Id, previousType, previousId); 1209 previousId = this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.PayloadGroup, id, previousType, previousId);
1193 previousType = ComplexReferenceChildType.PayloadGroup; 1210 previousType = ComplexReferenceChildType.PayloadGroup;
1194 break; 1211 break;
1195 default: 1212 default:
@@ -1206,9 +1223,9 @@ namespace WixToolset.Core
1206 1223
1207 if (!this.Core.EncounteredError) 1224 if (!this.Core.EncounteredError)
1208 { 1225 {
1209 this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundlePayloadGroup, id); 1226 this.Core.AddTuple(new WixBundlePayloadGroupTuple(sourceLineNumbers, id));
1210 1227
1211 this.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId, ComplexReferenceChildType.PayloadGroup, id.Id, ComplexReferenceChildType.Unknown, null); 1228 this.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId?.Id, ComplexReferenceChildType.PayloadGroup, id.Id, ComplexReferenceChildType.Unknown, null);
1212 } 1229 }
1213 } 1230 }
1214 1231
@@ -1218,13 +1235,13 @@ namespace WixToolset.Core
1218 /// <param name="node">Element to parse.</param> 1235 /// <param name="node">Element to parse.</param>
1219 /// <param name="parentType">ComplexReferenceParentType of parent element (BA or PayloadGroup).</param> 1236 /// <param name="parentType">ComplexReferenceParentType of parent element (BA or PayloadGroup).</param>
1220 /// <param name="parentId">Identifier of parent element.</param> 1237 /// <param name="parentId">Identifier of parent element.</param>
1221 private string ParsePayloadGroupRefElement(XElement node, ComplexReferenceParentType parentType, string parentId, ComplexReferenceChildType previousType, string previousId) 1238 private Identifier ParsePayloadGroupRefElement(XElement node, ComplexReferenceParentType parentType, Identifier parentId, ComplexReferenceChildType previousType, Identifier previousId)
1222 { 1239 {
1223 Debug.Assert(ComplexReferenceParentType.Layout == parentType || ComplexReferenceParentType.PayloadGroup == parentType || ComplexReferenceParentType.Package == parentType || ComplexReferenceParentType.Container == parentType); 1240 Debug.Assert(ComplexReferenceParentType.Layout == parentType || ComplexReferenceParentType.PayloadGroup == parentType || ComplexReferenceParentType.Package == parentType || ComplexReferenceParentType.Container == parentType);
1224 Debug.Assert(ComplexReferenceChildType.Unknown == previousType || ComplexReferenceChildType.PayloadGroup == previousType || ComplexReferenceChildType.Payload == previousType); 1241 Debug.Assert(ComplexReferenceChildType.Unknown == previousType || ComplexReferenceChildType.PayloadGroup == previousType || ComplexReferenceChildType.Payload == previousType);
1225 1242
1226 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); 1243 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
1227 string id = null; 1244 Identifier id = null;
1228 1245
1229 foreach (var attrib in node.Attributes()) 1246 foreach (var attrib in node.Attributes())
1230 { 1247 {
@@ -1233,8 +1250,8 @@ namespace WixToolset.Core
1233 switch (attrib.Name.LocalName) 1250 switch (attrib.Name.LocalName)
1234 { 1251 {
1235 case "Id": 1252 case "Id":
1236 id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); 1253 id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib);
1237 this.Core.CreateSimpleReference(sourceLineNumbers, "WixBundlePayloadGroup", id); 1254 this.Core.CreateSimpleReference(sourceLineNumbers, "WixBundlePayloadGroup", id.Id);
1238 break; 1255 break;
1239 default: 1256 default:
1240 this.Core.UnexpectedAttribute(node, attrib); 1257 this.Core.UnexpectedAttribute(node, attrib);
@@ -1254,7 +1271,7 @@ namespace WixToolset.Core
1254 1271
1255 this.Core.ParseForExtensionElements(node); 1272 this.Core.ParseForExtensionElements(node);
1256 1273
1257 this.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId, ComplexReferenceChildType.PayloadGroup, id, previousType, previousId); 1274 this.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId.Id, ComplexReferenceChildType.PayloadGroup, id.Id, previousType, previousId.Id);
1258 1275
1259 return id; 1276 return id;
1260 } 1277 }
@@ -1274,6 +1291,11 @@ namespace WixToolset.Core
1274 ComplexReferenceChildType type, string id, 1291 ComplexReferenceChildType type, string id,
1275 ComplexReferenceChildType previousType, string previousId) 1292 ComplexReferenceChildType previousType, string previousId)
1276 { 1293 {
1294 if (this.Core.EncounteredError)
1295 {
1296 return;
1297 }
1298
1277 if (ComplexReferenceParentType.Unknown != parentType && null != parentId) 1299 if (ComplexReferenceParentType.Unknown != parentType && null != parentId)
1278 { 1300 {
1279 this.Core.CreateWixGroupRow(sourceLineNumbers, parentType, parentId, type, id); 1301 this.Core.CreateWixGroupRow(sourceLineNumbers, parentType, parentId, type, id);
@@ -1281,7 +1303,18 @@ namespace WixToolset.Core
1281 1303
1282 if (ComplexReferenceChildType.Unknown != previousType && null != previousId) 1304 if (ComplexReferenceChildType.Unknown != previousType && null != previousId)
1283 { 1305 {
1284 this.CreateWixOrderingRow(sourceLineNumbers, type, id, previousType, previousId); 1306 // TODO: Should we define our own enum for this, just to ensure there's no "cross-contamination"?
1307 // TODO: Also, we could potentially include an 'Attributes' field to track things like
1308 // 'before' vs. 'after', and explicit vs. inferred dependencies.
1309 var tuple = new WixOrderingTuple(sourceLineNumbers)
1310 {
1311 ItemType = type,
1312 ItemId_ = id,
1313 DependsOnType = previousType,
1314 DependsOnId_ = previousId
1315 };
1316
1317 this.Core.AddTuple(tuple);
1285 } 1318 }
1286 } 1319 }
1287 1320
@@ -1307,7 +1340,7 @@ namespace WixToolset.Core
1307 break; 1340 break;
1308 case "Behavior": 1341 case "Behavior":
1309 var behaviorString = this.Core.GetAttributeValue(sourceLineNumbers, attrib); 1342 var behaviorString = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1310 if (!Enum.TryParse<ExitCodeBehaviorType>(behaviorString, true, out behavior)) 1343 if (!Enum.TryParse(behaviorString, true, out behavior))
1311 { 1344 {
1312 this.Core.Write(ErrorMessages.IllegalAttributeValueWithLegalList(sourceLineNumbers, node.Name.LocalName, "Behavior", behaviorString, "success, error, scheduleReboot, forceReboot")); 1345 this.Core.Write(ErrorMessages.IllegalAttributeValueWithLegalList(sourceLineNumbers, node.Name.LocalName, "Behavior", behaviorString, "success, error, scheduleReboot, forceReboot"));
1313 } 1346 }
@@ -1332,10 +1365,12 @@ namespace WixToolset.Core
1332 1365
1333 if (!this.Core.EncounteredError) 1366 if (!this.Core.EncounteredError)
1334 { 1367 {
1335 var row = (WixBundlePackageExitCodeTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundlePackageExitCode); 1368 this.Core.AddTuple(new WixBundlePackageExitCodeTuple(sourceLineNumbers)
1336 row.ChainPackageId = packageId; 1369 {
1337 row.Code = value; 1370 ChainPackageId = packageId,
1338 row.Behavior = behavior; 1371 Code = value,
1372 Behavior = behavior
1373 });
1339 } 1374 }
1340 } 1375 }
1341 1376
@@ -1384,7 +1419,7 @@ namespace WixToolset.Core
1384 } 1419 }
1385 1420
1386 // Ensure there is always a rollback boundary at the beginning of the chain. 1421 // Ensure there is always a rollback boundary at the beginning of the chain.
1387 this.CreateRollbackBoundary(sourceLineNumbers, new Identifier("WixDefaultBoundary", AccessModifier.Public), YesNoType.Yes, YesNoType.No, ComplexReferenceParentType.PackageGroup, "WixChain", ComplexReferenceChildType.Unknown, null); 1422 this.CreateRollbackBoundary(sourceLineNumbers, new Identifier(AccessModifier.Public, "WixDefaultBoundary"), YesNoType.Yes, YesNoType.No, ComplexReferenceParentType.PackageGroup, "WixChain", ComplexReferenceChildType.Unknown, null);
1388 1423
1389 var previousId = "WixDefaultBoundary"; 1424 var previousId = "WixDefaultBoundary";
1390 var previousType = ComplexReferenceChildType.Package; 1425 var previousType = ComplexReferenceChildType.Package;
@@ -1438,8 +1473,10 @@ namespace WixToolset.Core
1438 1473
1439 if (!this.Core.EncounteredError) 1474 if (!this.Core.EncounteredError)
1440 { 1475 {
1441 var row = (WixChainTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixChain); 1476 this.Core.AddTuple(new WixChainTuple(sourceLineNumbers)
1442 row.Attributes = attributes; 1477 {
1478 Attributes = attributes
1479 });
1443 } 1480 }
1444 } 1481 }
1445 1482
@@ -1680,7 +1717,24 @@ namespace WixToolset.Core
1680 installCondition = this.Core.GetAttributeValue(sourceLineNumbers, attrib); 1717 installCondition = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1681 break; 1718 break;
1682 case "Cache": 1719 case "Cache":
1683 cache = this.Core.GetAttributeYesNoAlwaysValue(sourceLineNumbers, attrib); 1720 var value = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1721 switch (value)
1722 {
1723 case "always":
1724 cache = YesNoAlwaysType.Always;
1725 break;
1726 case "yes":
1727 cache = YesNoAlwaysType.Yes;
1728 break;
1729 case "no":
1730 cache = YesNoAlwaysType.No;
1731 break;
1732 case "":
1733 break;
1734 default:
1735 this.Core.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, value, "button", "yes", "no"));
1736 break;
1737 }
1684 break; 1738 break;
1685 case "CacheId": 1739 case "CacheId":
1686 cacheId = this.Core.GetAttributeValue(sourceLineNumbers, attrib); 1740 cacheId = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
@@ -1933,10 +1987,10 @@ namespace WixToolset.Core
1933 } 1987 }
1934 break; 1988 break;
1935 case "Payload": 1989 case "Payload":
1936 this.ParsePayloadElement(child, ComplexReferenceParentType.Package, id.Id, ComplexReferenceChildType.Unknown, null); 1990 this.ParsePayloadElement(child, ComplexReferenceParentType.Package, id, ComplexReferenceChildType.Unknown, null);
1937 break; 1991 break;
1938 case "PayloadGroupRef": 1992 case "PayloadGroupRef":
1939 this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Package, id.Id, ComplexReferenceChildType.Unknown, null); 1993 this.ParsePayloadGroupRefElement(child, ComplexReferenceParentType.Package, id, ComplexReferenceChildType.Unknown, null);
1940 break; 1994 break;
1941 case "ExitCode": 1995 case "ExitCode":
1942 allowed = (packageType == WixBundlePackageType.Exe); 1996 allowed = (packageType == WixBundlePackageType.Exe);
@@ -1975,60 +2029,60 @@ namespace WixToolset.Core
1975 if (!this.Core.EncounteredError) 2029 if (!this.Core.EncounteredError)
1976 { 2030 {
1977 // We create the package contents as a payload with this package as the parent 2031 // We create the package contents as a payload with this package as the parent
1978 this.CreatePayloadRow(sourceLineNumbers, id, name, sourceFile, downloadUrl, ComplexReferenceParentType.Package, id.Id, 2032 this.CreatePayloadRow(sourceLineNumbers, id, name, sourceFile, downloadUrl, ComplexReferenceParentType.Package, id,
1979 ComplexReferenceChildType.Unknown, null, compressed, enableSignatureVerification, displayName, description, remotePayload); 2033 ComplexReferenceChildType.Unknown, null, compressed, enableSignatureVerification, displayName, description, remotePayload);
1980 2034
1981 var chainItemRow = (WixChainItemTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixChainItem, id); 2035 this.Core.AddTuple(new WixChainItemTuple(sourceLineNumbers, id));
1982 2036
1983 WixBundlePackageAttributes attributes = 0; 2037 WixBundlePackageAttributes attributes = 0;
1984 attributes |= (YesNoType.Yes == permanent) ? WixBundlePackageAttributes.Permanent : 0; 2038 attributes |= (YesNoType.Yes == permanent) ? WixBundlePackageAttributes.Permanent : 0;
1985 attributes |= (YesNoType.Yes == visible) ? WixBundlePackageAttributes.Visible : 0; 2039 attributes |= (YesNoType.Yes == visible) ? WixBundlePackageAttributes.Visible : 0;
1986 2040
1987 var chainPackageRow = (WixBundlePackageTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundlePackage, id); 2041 var chainPackageTuple = new WixBundlePackageTuple(sourceLineNumbers, id)
1988 chainPackageRow.Type = packageType; 2042 {
1989 chainPackageRow.Payload_ = id.Id; 2043 Type = packageType,
1990 chainPackageRow.Attributes = attributes; 2044 Payload_ = id.Id,
1991 2045 Attributes = attributes,
1992 chainPackageRow.InstallCondition = installCondition; 2046 InstallCondition = installCondition,
2047 CacheId = cacheId,
2048 LogPathVariable = logPathVariable,
2049 RollbackLogPathVariable = rollbackPathVariable,
2050 };
1993 2051
1994 if (YesNoAlwaysType.NotSet != cache) 2052 if (YesNoAlwaysType.NotSet != cache)
1995 { 2053 {
1996 chainPackageRow.Cache = cache; 2054 chainPackageTuple.Cache = cache;
1997 } 2055 }
1998 2056
1999 chainPackageRow.CacheId = cacheId;
2000
2001 if (YesNoType.NotSet != vital) 2057 if (YesNoType.NotSet != vital)
2002 { 2058 {
2003 chainPackageRow.Vital = (vital == YesNoType.Yes); 2059 chainPackageTuple.Vital = (vital == YesNoType.Yes);
2004 } 2060 }
2005 2061
2006 if (YesNoDefaultType.NotSet != perMachine) 2062 if (YesNoDefaultType.NotSet != perMachine)
2007 { 2063 {
2008 chainPackageRow.PerMachine = perMachine; 2064 chainPackageTuple.PerMachine = perMachine;
2009 } 2065 }
2010 2066
2011 chainPackageRow.LogPathVariable = logPathVariable;
2012 chainPackageRow.RollbackLogPathVariable = rollbackPathVariable;
2013
2014 if (CompilerConstants.IntegerNotSet != installSize) 2067 if (CompilerConstants.IntegerNotSet != installSize)
2015 { 2068 {
2016 chainPackageRow.InstallSize = installSize; 2069 chainPackageTuple.InstallSize = installSize;
2017 } 2070 }
2018 2071
2072 this.Core.AddTuple(chainPackageTuple);
2073
2019 switch (packageType) 2074 switch (packageType)
2020 { 2075 {
2021 case WixBundlePackageType.Exe: 2076 case WixBundlePackageType.Exe:
2022 WixBundleExePackageAttributes exeAttributes = 0; 2077 this.Core.AddTuple(new WixBundleExePackageTuple(sourceLineNumbers, id)
2023 exeAttributes |= (YesNoType.Yes == repairable) ? WixBundleExePackageAttributes.Repairable : 0; 2078 {
2024 2079 Attributes = (YesNoType.Yes == repairable) ? WixBundleExePackageAttributes.Repairable : 0,
2025 var exeRow = (WixBundleExePackageTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleExePackage, id); 2080 DetectCondition = detectCondition,
2026 exeRow.Attributes = exeAttributes; 2081 InstallCommand = installCommand,
2027 exeRow.DetectCondition = detectCondition; 2082 RepairCommand = repairCommand,
2028 exeRow.InstallCommand = installCommand; 2083 UninstallCommand = uninstallCommand,
2029 exeRow.RepairCommand = repairCommand; 2084 ExeProtocol = protocol
2030 exeRow.UninstallCommand = uninstallCommand; 2085 });
2031 exeRow.ExeProtocol = protocol;
2032 break; 2086 break;
2033 2087
2034 case WixBundlePackageType.Msi: 2088 case WixBundlePackageType.Msi:
@@ -2038,8 +2092,10 @@ namespace WixToolset.Core
2038 msiAttributes |= (YesNoType.Yes == forcePerMachine) ? WixBundleMsiPackageAttributes.ForcePerMachine : 0; 2092 msiAttributes |= (YesNoType.Yes == forcePerMachine) ? WixBundleMsiPackageAttributes.ForcePerMachine : 0;
2039 msiAttributes |= (YesNoType.Yes == suppressLooseFilePayloadGeneration) ? WixBundleMsiPackageAttributes.SuppressLooseFilePayloadGeneration : 0; 2093 msiAttributes |= (YesNoType.Yes == suppressLooseFilePayloadGeneration) ? WixBundleMsiPackageAttributes.SuppressLooseFilePayloadGeneration : 0;
2040 2094
2041 var msiRow = (WixBundleMsiPackageTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleMsiPackage, id); 2095 this.Core.AddTuple(new WixBundleMsiPackageTuple(sourceLineNumbers, id)
2042 msiRow.Attributes = msiAttributes; 2096 {
2097 Attributes = msiAttributes
2098 });
2043 break; 2099 break;
2044 2100
2045 case WixBundlePackageType.Msp: 2101 case WixBundlePackageType.Msp:
@@ -2047,14 +2103,18 @@ namespace WixToolset.Core
2047 mspAttributes |= (YesNoType.Yes == displayInternalUI) ? WixBundleMspPackageAttributes.DisplayInternalUI : 0; 2103 mspAttributes |= (YesNoType.Yes == displayInternalUI) ? WixBundleMspPackageAttributes.DisplayInternalUI : 0;
2048 mspAttributes |= (YesNoType.Yes == slipstream) ? WixBundleMspPackageAttributes.Slipstream : 0; 2104 mspAttributes |= (YesNoType.Yes == slipstream) ? WixBundleMspPackageAttributes.Slipstream : 0;
2049 2105
2050 var mspRow = (WixBundleMspPackageTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleMspPackage, id); 2106 this.Core.AddTuple(new WixBundleMspPackageTuple(sourceLineNumbers, id)
2051 mspRow.Attributes = mspAttributes; 2107 {
2108 Attributes = mspAttributes
2109 });
2052 break; 2110 break;
2053 2111
2054 case WixBundlePackageType.Msu: 2112 case WixBundlePackageType.Msu:
2055 var msuRow = (WixBundleMsuPackageTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleMsuPackage, id); 2113 this.Core.AddTuple(new WixBundleMsuPackageTuple(sourceLineNumbers, id)
2056 msuRow.DetectCondition = detectCondition; 2114 {
2057 msuRow.MsuKB = msuKB; 2115 DetectCondition = detectCondition,
2116 MsuKB = msuKB
2117 });
2058 break; 2118 break;
2059 } 2119 }
2060 2120
@@ -2114,12 +2174,14 @@ namespace WixToolset.Core
2114 2174
2115 if (!this.Core.EncounteredError) 2175 if (!this.Core.EncounteredError)
2116 { 2176 {
2117 var row = (WixBundlePackageCommandLineTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundlePackageCommandLine); 2177 this.Core.AddTuple(new WixBundlePackageCommandLineTuple(sourceLineNumbers)
2118 row.WixBundlePackage_ = packageId; 2178 {
2119 row.InstallArgument = installArgument; 2179 WixBundlePackage_ = packageId,
2120 row.UninstallArgument = uninstallArgument; 2180 InstallArgument = installArgument,
2121 row.RepairArgument = repairArgument; 2181 UninstallArgument = uninstallArgument,
2122 row.Condition = condition; 2182 RepairArgument = repairArgument,
2183 Condition = condition
2184 });
2123 } 2185 }
2124 } 2186 }
2125 2187
@@ -2204,7 +2266,7 @@ namespace WixToolset.Core
2204 2266
2205 if (!this.Core.EncounteredError) 2267 if (!this.Core.EncounteredError)
2206 { 2268 {
2207 this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundlePackageGroup, id); 2269 this.Core.AddTuple(new WixBundlePackageGroupTuple(sourceLineNumbers, id));
2208 } 2270 }
2209 } 2271 }
2210 2272
@@ -2299,19 +2361,22 @@ namespace WixToolset.Core
2299 /// <param name="previousId">Identifier of previous item, if any.</param> 2361 /// <param name="previousId">Identifier of previous item, if any.</param>
2300 private void CreateRollbackBoundary(SourceLineNumber sourceLineNumbers, Identifier id, YesNoType vital, YesNoType transaction, ComplexReferenceParentType parentType, string parentId, ComplexReferenceChildType previousType, string previousId) 2362 private void CreateRollbackBoundary(SourceLineNumber sourceLineNumbers, Identifier id, YesNoType vital, YesNoType transaction, ComplexReferenceParentType parentType, string parentId, ComplexReferenceChildType previousType, string previousId)
2301 { 2363 {
2302 var row = (WixChainItemTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixChainItem, id); 2364 this.Core.AddTuple(new WixChainItemTuple(sourceLineNumbers, id));
2303 2365
2304 var rollbackBoundary = (WixBundleRollbackBoundaryTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleRollbackBoundary, id); 2366 var rollbackBoundary = new WixBundleRollbackBoundaryTuple(sourceLineNumbers, id);
2305 2367
2306 if (YesNoType.NotSet != vital) 2368 if (YesNoType.NotSet != vital)
2307 { 2369 {
2308 rollbackBoundary.Vital = (vital == YesNoType.Yes); 2370 rollbackBoundary.Vital = (vital == YesNoType.Yes);
2309 } 2371 }
2372
2310 if (YesNoType.NotSet != transaction) 2373 if (YesNoType.NotSet != transaction)
2311 { 2374 {
2312 rollbackBoundary.Transaction = (transaction == YesNoType.Yes); 2375 rollbackBoundary.Transaction = (transaction == YesNoType.Yes);
2313 } 2376 }
2314 2377
2378 this.Core.AddTuple(rollbackBoundary);
2379
2315 this.CreateChainPackageMetaRows(sourceLineNumbers, parentType, parentId, ComplexReferenceChildType.Package, id.Id, previousType, previousId, null); 2380 this.CreateChainPackageMetaRows(sourceLineNumbers, parentType, parentId, ComplexReferenceChildType.Package, id.Id, previousType, previousId, null);
2316 } 2381 }
2317 2382
@@ -2341,23 +2406,6 @@ namespace WixToolset.Core
2341 this.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId, type, id, previousType, previousId); 2406 this.CreateGroupAndOrderingRows(sourceLineNumbers, parentType, parentId, type, id, previousType, previousId);
2342 } 2407 }
2343 2408
2344 // TODO: Should we define our own enum for this, just to ensure there's no "cross-contamination"?
2345 // TODO: Also, we could potentially include an 'Attributes' field to track things like
2346 // 'before' vs. 'after', and explicit vs. inferred dependencies.
2347 private void CreateWixOrderingRow(SourceLineNumber sourceLineNumbers,
2348 ComplexReferenceChildType itemType, string itemId,
2349 ComplexReferenceChildType dependsOnType, string dependsOnId)
2350 {
2351 if (!this.Core.EncounteredError)
2352 {
2353 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixOrdering);
2354 row.Set(0, itemType.ToString());
2355 row.Set(1, itemId);
2356 row.Set(2, dependsOnType.ToString());
2357 row.Set(3, dependsOnId);
2358 }
2359 }
2360
2361 /// <summary> 2409 /// <summary>
2362 /// Parse MsiProperty element 2410 /// Parse MsiProperty element
2363 /// </summary> 2411 /// </summary>
@@ -2410,15 +2458,19 @@ namespace WixToolset.Core
2410 2458
2411 if (!this.Core.EncounteredError) 2459 if (!this.Core.EncounteredError)
2412 { 2460 {
2413 var row = (WixBundleMsiPropertyTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleMsiProperty); 2461 var tuple = new WixBundleMsiPropertyTuple(sourceLineNumbers)
2414 row.WixBundlePackage_ = packageId; 2462 {
2415 row.Name = name; 2463 WixBundlePackage_ = packageId,
2416 row.Value = value; 2464 Name = name,
2465 Value = value
2466 };
2417 2467
2418 if (!String.IsNullOrEmpty(condition)) 2468 if (!String.IsNullOrEmpty(condition))
2419 { 2469 {
2420 row.Condition = condition; 2470 tuple.Condition = condition;
2421 } 2471 }
2472
2473 this.Core.AddTuple(tuple);
2422 } 2474 }
2423 } 2475 }
2424 2476
@@ -2462,9 +2514,11 @@ namespace WixToolset.Core
2462 2514
2463 if (!this.Core.EncounteredError) 2515 if (!this.Core.EncounteredError)
2464 { 2516 {
2465 var row = (WixBundleSlipstreamMspTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleSlipstreamMsp); 2517 this.Core.AddTuple(new WixBundleSlipstreamMspTuple(sourceLineNumbers)
2466 row.WixBundlePackage_ = packageId; 2518 {
2467 row.WixBundlePackage_Msp = id; 2519 WixBundlePackage_ = packageId,
2520 WixBundlePackage_Msp = id
2521 });
2468 } 2522 }
2469 } 2523 }
2470 2524
@@ -2585,8 +2639,12 @@ namespace WixToolset.Core
2585 2639
2586 if (!this.Core.EncounteredError) 2640 if (!this.Core.EncounteredError)
2587 { 2641 {
2588 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleUpdate); 2642 var tuple = new WixBundleUpdateTuple(sourceLineNumbers)
2589 row.Set(0, location); 2643 {
2644 Location = location
2645 };
2646
2647 this.Core.AddTuple(tuple);
2590 } 2648 }
2591 } 2649 }
2592 2650
@@ -2698,12 +2756,15 @@ namespace WixToolset.Core
2698 2756
2699 if (!this.Core.EncounteredError) 2757 if (!this.Core.EncounteredError)
2700 { 2758 {
2701 var row = (WixBundleVariableTuple)this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixBundleVariable); 2759 var tuple = new WixBundleVariableTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, name))
2702 row.WixBundleVariable = name; 2760 {
2703 row.Value = value; 2761 Value = value,
2704 row.Type = type; 2762 Type = type,
2705 row.Hidden = hidden; 2763 Hidden = hidden,
2706 row.Persisted = persisted; 2764 Persisted = persisted
2765 };
2766
2767 this.Core.AddTuple(tuple);
2707 } 2768 }
2708 } 2769 }
2709 2770
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
91 91
92 if (!this.Core.EncounteredError) 92 if (!this.Core.EncounteredError)
93 { 93 {
94 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.MsiEmbeddedChainer, id); 94 this.Core.AddTuple(new MsiEmbeddedChainerTuple(sourceLineNumbers, id)
95 row.Set(1, condition); 95 {
96 row.Set(2, commandLine); 96 Condition = condition,
97 row.Set(3, source); 97 CommandLine = commandLine,
98 row.Set(4, type); 98 Source = source,
99 Type = type
100 });
99 } 101 }
100 } 102 }
101 103
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
100 switch (child.Name.LocalName) 100 switch (child.Name.LocalName)
101 { 101 {
102 case "AdminExecuteSequence": 102 case "AdminExecuteSequence":
103 this.ParseSequenceElement(child, SequenceTable.AdminExecuteSequence);
104 break;
103 case "AdminUISequence": 105 case "AdminUISequence":
106 this.ParseSequenceElement(child, SequenceTable.AdminUISequence);
107 break;
104 case "AdvertiseExecuteSequence": 108 case "AdvertiseExecuteSequence":
109 this.ParseSequenceElement(child, SequenceTable.AdvertiseExecuteSequence);
110 break;
105 case "InstallExecuteSequence": 111 case "InstallExecuteSequence":
112 this.ParseSequenceElement(child, SequenceTable.InstallExecuteSequence);
113 break;
106 case "InstallUISequence": 114 case "InstallUISequence":
107 this.ParseSequenceElement(child, child.Name.LocalName); 115 this.ParseSequenceElement(child, SequenceTable.InstallUISequence);
108 break; 116 break;
109 case "AppId": 117 case "AppId":
110 this.ParseAppIdElement(child, null, YesNoType.Yes, null, null, null); 118 this.ParseAppIdElement(child, null, YesNoType.Yes, null, null, null);
@@ -208,10 +216,15 @@ namespace WixToolset.Core
208 216
209 if (!this.Core.EncounteredError) 217 if (!this.Core.EncounteredError)
210 { 218 {
211 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ModuleSignature); 219 var tuple = new ModuleSignatureTuple(sourceLineNumbers, new Identifier(AccessModifier.Public, this.activeName, this.activeLanguage))
212 row.Set(0, this.activeName); 220 {
213 row.Set(1, this.activeLanguage); 221 ModuleID = this.activeName,
214 row.Set(2, version); 222 Version = version
223 };
224
225 tuple.Set((int)ModuleSignatureTupleFields.Language, this.activeLanguage);
226
227 this.Core.AddTuple(tuple);
215 } 228 }
216 } 229 }
217 finally 230 finally
@@ -273,12 +286,17 @@ namespace WixToolset.Core
273 286
274 if (!this.Core.EncounteredError) 287 if (!this.Core.EncounteredError)
275 { 288 {
276 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ModuleDependency); 289 var tuple = new ModuleDependencyTuple(sourceLineNumbers)
277 row.Set(0, this.activeName); 290 {
278 row.Set(1, this.activeLanguage); 291 ModuleID = this.activeName,
279 row.Set(2, requiredId); 292 RequiredID = requiredId,
280 row.Set(3, requiredLanguage.ToString(CultureInfo.InvariantCulture)); 293 RequiredLanguage = requiredLanguage,
281 row.Set(4, requiredVersion); 294 RequiredVersion = requiredVersion
295 };
296
297 tuple.Set((int)ModuleDependencyTupleFields.ModuleLanguage, this.activeLanguage);
298
299 this.Core.AddTuple(tuple);
282 } 300 }
283 } 301 }
284 302
@@ -351,13 +369,18 @@ namespace WixToolset.Core
351 369
352 if (!this.Core.EncounteredError) 370 if (!this.Core.EncounteredError)
353 { 371 {
354 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ModuleExclusion); 372 var tuple = new ModuleExclusionTuple(sourceLineNumbers)
355 row.Set(0, this.activeName); 373 {
356 row.Set(1, this.activeLanguage); 374 ModuleID = this.activeName,
357 row.Set(2, excludedId); 375 ExcludedID = excludedId,
358 row.Set(3, excludedLanguageField); 376 ExcludedMinVersion = excludedMinVersion,
359 row.Set(4, excludedMinVersion); 377 ExcludedMaxVersion = excludedMaxVersion
360 row.Set(5, excludedMaxVersion); 378 };
379
380 tuple.Set((int)ModuleExclusionTupleFields.ModuleLanguage, this.activeLanguage);
381 tuple.Set((int)ModuleExclusionTupleFields.ExcludedLanguage, excludedLanguageField);
382
383 this.Core.AddTuple(tuple);
361 } 384 }
362 } 385 }
363 386
@@ -548,11 +571,15 @@ namespace WixToolset.Core
548 571
549 if (!this.Core.EncounteredError) 572 if (!this.Core.EncounteredError)
550 { 573 {
551 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ModuleSubstitution); 574 var tuple = new ModuleSubstitutionTuple(sourceLineNumbers)
552 row.Set(0, table); 575 {
553 row.Set(1, rowKeys); 576 Table = table,
554 row.Set(2, column); 577 Row = rowKeys,
555 row.Set(3, value); 578 Column = column,
579 Value = value
580 };
581
582 this.Core.AddTuple(tuple);
556 } 583 }
557 } 584 }
558 585
@@ -599,8 +626,7 @@ namespace WixToolset.Core
599 626
600 if (!this.Core.EncounteredError) 627 if (!this.Core.EncounteredError)
601 { 628 {
602 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixSuppressModularization); 629 this.Core.AddTuple(new WixSuppressModularizationTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, name)));
603 row.Set(0, name);
604 } 630 }
605 } 631 }
606 632
@@ -642,8 +668,7 @@ namespace WixToolset.Core
642 668
643 if (!this.Core.EncounteredError) 669 if (!this.Core.EncounteredError)
644 { 670 {
645 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ModuleIgnoreTable); 671 this.Core.AddTuple(new ModuleIgnoreTableTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, id)));
646 row.Set(0, id);
647 } 672 }
648 } 673 }
649 } 674 }
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 @@
1// 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.
2
3namespace WixToolset.Core
4{
5 using System;
6 using System.Collections.Generic;
7 using System.Diagnostics;
8 using System.Globalization;
9 using System.Xml.Linq;
10 using WixToolset.Data;
11 using WixToolset.Data.Tuples;
12 using WixToolset.Extensibility;
13
14 /// <summary>
15 /// Compiler of the WiX toolset.
16 /// </summary>
17 internal partial class Compiler : ICompiler
18 {
19 /// <summary>
20 /// Parses an patch element.
21 /// </summary>
22 /// <param name="node">The element to parse.</param>
23 private void ParsePatchElement(XElement node)
24 {
25 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
26 string patchId = null;
27 var codepage = 0;
28 ////bool versionMismatches = false;
29 ////bool productMismatches = false;
30 var allowRemoval = false;
31 string classification = null;
32 string clientPatchId = null;
33 string description = null;
34 string displayName = null;
35 string comments = null;
36 string manufacturer = null;
37 var minorUpdateTargetRTM = YesNoType.NotSet;
38 string moreInfoUrl = null;
39 var optimizeCA = CompilerConstants.IntegerNotSet;
40 var optimizedInstallMode = YesNoType.NotSet;
41 string targetProductName = null;
42 // string replaceGuids = String.Empty;
43 var apiPatchingSymbolFlags = 0;
44 var optimizePatchSizeForLargeFiles = false;
45
46 foreach (var attrib in node.Attributes())
47 {
48 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
49 {
50 switch (attrib.Name.LocalName)
51 {
52 case "Id":
53 patchId = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, true);
54 break;
55 case "Codepage":
56 codepage = this.Core.GetAttributeCodePageValue(sourceLineNumbers, attrib);
57 break;
58 case "AllowMajorVersionMismatches":
59 ////versionMismatches = (YesNoType.Yes == this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib));
60 break;
61 case "AllowProductCodeMismatches":
62 ////productMismatches = (YesNoType.Yes == this.core.GetAttributeYesNoValue(sourceLineNumbers, attrib));
63 break;
64 case "AllowRemoval":
65 allowRemoval = (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib));
66 break;
67 case "Classification":
68 classification = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
69 break;
70 case "ClientPatchId":
71 clientPatchId = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
72 break;
73 case "Description":
74 description = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
75 break;
76 case "DisplayName":
77 displayName = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
78 break;
79 case "Comments":
80 comments = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
81 break;
82 case "Manufacturer":
83 manufacturer = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
84 break;
85 case "MinorUpdateTargetRTM":
86 minorUpdateTargetRTM = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
87 break;
88 case "MoreInfoURL":
89 moreInfoUrl = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
90 break;
91 case "OptimizedInstallMode":
92 optimizedInstallMode = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
93 break;
94 case "TargetProductName":
95 targetProductName = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
96 break;
97 case "ApiPatchingSymbolNoImagehlpFlag":
98 apiPatchingSymbolFlags |= (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) ? (int)PatchSymbolFlagsType.PATCH_SYMBOL_NO_IMAGEHLP : 0;
99 break;
100 case "ApiPatchingSymbolNoFailuresFlag":
101 apiPatchingSymbolFlags |= (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) ? (int)PatchSymbolFlagsType.PATCH_SYMBOL_NO_FAILURES : 0;
102 break;
103 case "ApiPatchingSymbolUndecoratedTooFlag":
104 apiPatchingSymbolFlags |= (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib)) ? (int)PatchSymbolFlagsType.PATCH_SYMBOL_UNDECORATED_TOO : 0;
105 break;
106 case "OptimizePatchSizeForLargeFiles":
107 optimizePatchSizeForLargeFiles = (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib));
108 break;
109 default:
110 this.Core.UnexpectedAttribute(node, attrib);
111 break;
112 }
113 }
114 else
115 {
116 this.Core.ParseExtensionAttribute(node, attrib);
117 }
118 }
119
120 if (patchId == null || patchId == "*")
121 {
122 // auto-generate at compile time, since this value gets dispersed to several locations
123 patchId = Common.GenerateGuid();
124 }
125 this.activeName = patchId;
126
127 if (null == this.activeName)
128 {
129 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
130 }
131 if (null == classification)
132 {
133 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Classification"));
134 }
135 if (null == clientPatchId)
136 {
137 clientPatchId = String.Concat("_", new Guid(patchId).ToString("N", CultureInfo.InvariantCulture).ToUpper(CultureInfo.InvariantCulture));
138 }
139 if (null == description)
140 {
141 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Description"));
142 }
143 if (null == displayName)
144 {
145 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "DisplayName"));
146 }
147 if (null == manufacturer)
148 {
149 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Manufacturer"));
150 }
151
152 this.Core.CreateActiveSection(this.activeName, SectionType.Patch, codepage, this.Context.CompilationId);
153
154 foreach (var child in node.Elements())
155 {
156 if (CompilerCore.WixNamespace == child.Name.Namespace)
157 {
158 switch (child.Name.LocalName)
159 {
160 case "PatchInformation":
161 this.ParsePatchInformationElement(child);
162 break;
163 case "Media":
164 this.ParseMediaElement(child, patchId);
165 break;
166 case "OptimizeCustomActions":
167 optimizeCA = this.ParseOptimizeCustomActionsElement(child);
168 break;
169 case "PatchFamily":
170 this.ParsePatchFamilyElement(child, ComplexReferenceParentType.Patch, patchId);
171 break;
172 case "PatchFamilyRef":
173 this.ParsePatchFamilyRefElement(child, ComplexReferenceParentType.Patch, patchId);
174 break;
175 case "PatchFamilyGroup":
176 this.ParsePatchFamilyGroupElement(child, ComplexReferenceParentType.Patch, patchId);
177 break;
178 case "PatchFamilyGroupRef":
179 this.ParsePatchFamilyGroupRefElement(child, ComplexReferenceParentType.Patch, patchId);
180 break;
181 case "PatchProperty":
182 this.ParsePatchPropertyElement(child, true);
183 break;
184 case "TargetProductCodes":
185 this.ParseTargetProductCodesElement(child);
186 break;
187 default:
188 this.Core.UnexpectedElement(node, child);
189 break;
190 }
191 }
192 else
193 {
194 this.Core.ParseExtensionElement(node, child);
195 }
196 }
197
198 if (!this.Core.EncounteredError)
199 {
200 var tuple = new WixPatchIdTuple(sourceLineNumbers)
201 {
202 ProductCode = patchId,
203 ClientPatchId = clientPatchId,
204 OptimizePatchSizeForLargeFiles = optimizePatchSizeForLargeFiles,
205 ApiPatchingSymbolFlags = apiPatchingSymbolFlags
206 };
207
208 this.Core.AddTuple(tuple);
209
210 if (allowRemoval)
211 {
212 this.AddMsiPatchMetadata(sourceLineNumbers, null, "AllowRemoval", allowRemoval ? "1" : "0");
213 }
214
215 if (null != classification)
216 {
217 this.AddMsiPatchMetadata(sourceLineNumbers, null, "Classification", classification);
218 }
219
220 // always generate the CreationTimeUTC
221 {
222 this.AddMsiPatchMetadata(sourceLineNumbers, null, "CreationTimeUTC", DateTime.UtcNow.ToString("MM-dd-yy HH:mm", CultureInfo.InvariantCulture));
223 }
224
225 if (null != description)
226 {
227 this.AddMsiPatchMetadata(sourceLineNumbers, null, "Description", description);
228 }
229
230 if (null != displayName)
231 {
232 this.AddMsiPatchMetadata(sourceLineNumbers, null, "DisplayName", displayName);
233 }
234
235 if (null != manufacturer)
236 {
237 this.AddMsiPatchMetadata(sourceLineNumbers, null, "ManufacturerName", manufacturer);
238 }
239
240 if (YesNoType.NotSet != minorUpdateTargetRTM)
241 {
242 this.AddMsiPatchMetadata(sourceLineNumbers, null, "MinorUpdateTargetRTM", YesNoType.Yes == minorUpdateTargetRTM ? "1" : "0");
243 }
244
245 if (null != moreInfoUrl)
246 {
247 this.AddMsiPatchMetadata(sourceLineNumbers, null, "MoreInfoURL", moreInfoUrl);
248 }
249
250 if (CompilerConstants.IntegerNotSet != optimizeCA)
251 {
252 this.AddMsiPatchMetadata(sourceLineNumbers, null, "OptimizeCA", optimizeCA.ToString(CultureInfo.InvariantCulture));
253 }
254
255 if (YesNoType.NotSet != optimizedInstallMode)
256 {
257 this.AddMsiPatchMetadata(sourceLineNumbers, null, "OptimizedInstallMode", YesNoType.Yes == optimizedInstallMode ? "1" : "0");
258 }
259
260 if (null != targetProductName)
261 {
262 this.AddMsiPatchMetadata(sourceLineNumbers, null, "TargetProductName", targetProductName);
263 }
264
265 if (null != comments)
266 {
267 this.AddMsiPatchMetadata(sourceLineNumbers, null, "Comments", comments);
268 }
269 }
270 // TODO: do something with versionMismatches and productMismatches
271 }
272
273 /// <summary>
274 /// Parses the OptimizeCustomActions element.
275 /// </summary>
276 /// <param name="node">Element to parse.</param>
277 /// <returns>The combined integer value for callers to store as appropriate.</returns>
278 private int ParseOptimizeCustomActionsElement(XElement node)
279 {
280 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
281 var optimizeCA = OptimizeCA.None;
282
283 foreach (var attrib in node.Attributes())
284 {
285 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
286 {
287 switch (attrib.Name.LocalName)
288 {
289 case "SkipAssignment":
290 if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
291 {
292 optimizeCA |= OptimizeCA.SkipAssignment;
293 }
294 break;
295 case "SkipImmediate":
296 if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
297 {
298 optimizeCA |= OptimizeCA.SkipImmediate;
299 }
300 break;
301 case "SkipDeferred":
302 if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
303 {
304 optimizeCA |= OptimizeCA.SkipDeferred;
305 }
306 break;
307 default:
308 this.Core.UnexpectedAttribute(node, attrib);
309 break;
310 }
311 }
312 else
313 {
314 this.Core.ParseExtensionAttribute(node, attrib);
315 }
316 }
317
318 return (int)optimizeCA;
319 }
320
321 /// <summary>
322 /// Parses a PatchFamily element.
323 /// </summary>
324 /// <param name="node">The element to parse.</param>
325 private void ParsePatchFamilyElement(XElement node, ComplexReferenceParentType parentType, string parentId)
326 {
327 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
328 Identifier id = null;
329 string productCode = null;
330 string version = null;
331 var attributes = 0;
332
333 foreach (var attrib in node.Attributes())
334 {
335 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
336 {
337 switch (attrib.Name.LocalName)
338 {
339 case "Id":
340 id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib);
341 break;
342 case "ProductCode":
343 productCode = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false);
344 break;
345 case "Version":
346 version = this.Core.GetAttributeVersionValue(sourceLineNumbers, attrib);
347 break;
348 case "Supersede":
349 if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
350 {
351 attributes |= 0x1;
352 }
353 break;
354 default:
355 this.Core.UnexpectedAttribute(node, attrib);
356 break;
357 }
358 }
359 else
360 {
361 this.Core.ParseExtensionAttribute(node, attrib);
362 }
363 }
364
365 if (null == id)
366 {
367 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
368 id = Identifier.Invalid;
369 }
370
371 if (String.IsNullOrEmpty(version))
372 {
373 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Version"));
374 }
375 else if (!CompilerCore.IsValidProductVersion(version))
376 {
377 this.Core.Write(ErrorMessages.InvalidProductVersion(sourceLineNumbers, version));
378 }
379
380 // find unexpected child elements
381 foreach (var child in node.Elements())
382 {
383 if (CompilerCore.WixNamespace == child.Name.Namespace)
384 {
385 switch (child.Name.LocalName)
386 {
387 case "All":
388 this.ParseAllElement(child);
389 break;
390 case "BinaryRef":
391 this.ParsePatchChildRefElement(child, "Binary");
392 break;
393 case "ComponentRef":
394 this.ParsePatchChildRefElement(child, "Component");
395 break;
396 case "CustomActionRef":
397 this.ParsePatchChildRefElement(child, "CustomAction");
398 break;
399 case "DirectoryRef":
400 this.ParsePatchChildRefElement(child, "Directory");
401 break;
402 case "DigitalCertificateRef":
403 this.ParsePatchChildRefElement(child, "MsiDigitalCertificate");
404 break;
405 case "FeatureRef":
406 this.ParsePatchChildRefElement(child, "Feature");
407 break;
408 case "IconRef":
409 this.ParsePatchChildRefElement(child, "Icon");
410 break;
411 case "PropertyRef":
412 this.ParsePatchChildRefElement(child, "Property");
413 break;
414 case "UIRef":
415 this.ParsePatchChildRefElement(child, "WixUI");
416 break;
417 default:
418 this.Core.UnexpectedElement(node, child);
419 break;
420 }
421 }
422 else
423 {
424 this.Core.ParseExtensionElement(node, child);
425 }
426 }
427
428
429 if (!this.Core.EncounteredError)
430 {
431 var tuple = new MsiPatchSequenceTuple(sourceLineNumbers)
432 {
433 PatchFamily = id.Id,
434 ProductCode = productCode,
435 Sequence = version,
436 Attributes = attributes
437 };
438
439 this.Core.AddTuple(tuple);
440
441 if (ComplexReferenceParentType.Unknown != parentType)
442 {
443 this.Core.CreateComplexReference(sourceLineNumbers, parentType, parentId, null, ComplexReferenceChildType.PatchFamily, id.Id, ComplexReferenceParentType.Patch == parentType);
444 }
445 }
446 }
447
448 /// <summary>
449 /// Parses a PatchFamilyGroup element.
450 /// </summary>
451 /// <param name="node">Element to parse.</param>
452 [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1800:DoNotCastUnnecessarily")]
453 private void ParsePatchFamilyGroupElement(XElement node, ComplexReferenceParentType parentType, string parentId)
454 {
455 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
456 Identifier id = null;
457
458 foreach (var attrib in node.Attributes())
459 {
460 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
461 {
462 switch (attrib.Name.LocalName)
463 {
464 case "Id":
465 id = this.Core.GetAttributeIdentifier(sourceLineNumbers, attrib);
466 break;
467 default:
468 this.Core.UnexpectedAttribute(node, attrib);
469 break;
470 }
471 }
472 else
473 {
474 this.Core.ParseExtensionAttribute(node, attrib);
475 }
476 }
477
478 if (null == id)
479 {
480 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
481 id = Identifier.Invalid;
482 }
483
484 foreach (var child in node.Elements())
485 {
486 if (CompilerCore.WixNamespace == child.Name.Namespace)
487 {
488 switch (child.Name.LocalName)
489 {
490 case "PatchFamily":
491 this.ParsePatchFamilyElement(child, ComplexReferenceParentType.PatchFamilyGroup, id.Id);
492 break;
493 case "PatchFamilyRef":
494 this.ParsePatchFamilyRefElement(child, ComplexReferenceParentType.PatchFamilyGroup, id.Id);
495 break;
496 case "PatchFamilyGroupRef":
497 this.ParsePatchFamilyGroupRefElement(child, ComplexReferenceParentType.PatchFamilyGroup, id.Id);
498 break;
499 default:
500 this.Core.UnexpectedElement(node, child);
501 break;
502 }
503 }
504 else
505 {
506 this.Core.ParseExtensionElement(node, child);
507 }
508 }
509
510 if (!this.Core.EncounteredError)
511 {
512 this.Core.AddTuple(new WixPatchFamilyGroupTuple(sourceLineNumbers, id));
513
514 //Add this PatchFamilyGroup and its parent in WixGroup.
515 this.Core.CreateWixGroupRow(sourceLineNumbers, parentType, parentId, ComplexReferenceChildType.PatchFamilyGroup, id.Id);
516 }
517 }
518
519 /// <summary>
520 /// Parses a PatchFamilyGroup reference element.
521 /// </summary>
522 /// <param name="node">Element to parse.</param>
523 /// <param name="parentType">The type of parent.</param>
524 /// <param name="parentId">Identifier of parent element.</param>
525 private void ParsePatchFamilyGroupRefElement(XElement node, ComplexReferenceParentType parentType, string parentId)
526 {
527 Debug.Assert(ComplexReferenceParentType.PatchFamilyGroup == parentType || ComplexReferenceParentType.Patch == parentType);
528
529 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
530 string id = null;
531
532 foreach (var attrib in node.Attributes())
533 {
534 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
535 {
536 switch (attrib.Name.LocalName)
537 {
538 case "Id":
539 id = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
540 this.Core.CreateSimpleReference(sourceLineNumbers, "WixPatchFamilyGroup", id);
541 break;
542 default:
543 this.Core.UnexpectedAttribute(node, attrib);
544 break;
545 }
546 }
547 else
548 {
549 this.Core.ParseExtensionAttribute(node, attrib);
550 }
551 }
552
553 if (null == id)
554 {
555 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
556 }
557
558 this.Core.ParseForExtensionElements(node);
559
560 if (!this.Core.EncounteredError)
561 {
562 this.Core.CreateComplexReference(sourceLineNumbers, parentType, parentId, null, ComplexReferenceChildType.PatchFamilyGroup, id, true);
563 }
564 }
565
566 /// <summary>
567 /// Parses a TargetProductCodes element.
568 /// </summary>
569 /// <param name="node">The element to parse.</param>
570 private void ParseTargetProductCodesElement(XElement node)
571 {
572 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
573 var replace = false;
574 var targetProductCodes = new List<string>();
575
576 foreach (var attrib in node.Attributes())
577 {
578 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
579 {
580 switch (attrib.Name.LocalName)
581 {
582 case "Replace":
583 replace = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
584 break;
585 default:
586 this.Core.UnexpectedAttribute(node, attrib);
587 break;
588 }
589 }
590 else
591 {
592 this.Core.ParseExtensionAttribute(node, attrib);
593 }
594 }
595
596 foreach (var child in node.Elements())
597 {
598 if (CompilerCore.WixNamespace == child.Name.Namespace)
599 {
600 switch (child.Name.LocalName)
601 {
602 case "TargetProductCode":
603 var id = this.ParseTargetProductCodeElement(child);
604 if (0 == String.CompareOrdinal("*", id))
605 {
606 this.Core.Write(ErrorMessages.IllegalAttributeValueWhenNested(sourceLineNumbers, child.Name.LocalName, "Id", id, node.Name.LocalName));
607 }
608 else
609 {
610 targetProductCodes.Add(id);
611 }
612 break;
613 default:
614 this.Core.UnexpectedElement(node, child);
615 break;
616 }
617 }
618 else
619 {
620 this.Core.ParseExtensionElement(node, child);
621 }
622 }
623
624 if (!this.Core.EncounteredError)
625 {
626 // By default, target ProductCodes should be added.
627 if (!replace)
628 {
629 this.Core.AddTuple(new WixPatchTargetTuple(sourceLineNumbers)
630 {
631 ProductCode = "*"
632 });
633 }
634
635 foreach (var targetProductCode in targetProductCodes)
636 {
637 this.Core.AddTuple(new WixPatchTargetTuple(sourceLineNumbers)
638 {
639 ProductCode = targetProductCode
640 });
641 }
642 }
643 }
644
645 private void AddMsiPatchMetadata(SourceLineNumber sourceLineNumbers, string company, string property, string value)
646 {
647 this.Core.AddTuple(new MsiPatchMetadataTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, company, property))
648 {
649 Company = company,
650 Property = property,
651 Value = value
652 });
653 }
654 }
655}
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 @@
1// 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.
2
3namespace WixToolset.Core
4{
5 using System;
6 using System.Collections.Generic;
7 using System.Globalization;
8 using System.Xml.Linq;
9 using WixToolset.Data;
10 using WixToolset.Data.Tuples;
11 using WixToolset.Extensibility;
12
13 /// <summary>
14 /// Compiler of the WiX toolset.
15 /// </summary>
16 internal partial class Compiler : ICompiler
17 {
18 /// <summary>
19 /// Parses a patch creation element.
20 /// </summary>
21 /// <param name="node">The element to parse.</param>
22 private void ParsePatchCreationElement(XElement node)
23 {
24 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
25 var clean = true; // Default is to clean
26 var codepage = 0;
27 string outputPath = null;
28 var productMismatches = false;
29 var replaceGuids = String.Empty;
30 string sourceList = null;
31 string symbolFlags = null;
32 var targetProducts = String.Empty;
33 var versionMismatches = false;
34 var wholeFiles = false;
35
36 foreach (var attrib in node.Attributes())
37 {
38 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
39 {
40 switch (attrib.Name.LocalName)
41 {
42 case "Id":
43 this.activeName = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false);
44 break;
45 case "AllowMajorVersionMismatches":
46 versionMismatches = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
47 break;
48 case "AllowProductCodeMismatches":
49 productMismatches = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
50 break;
51 case "CleanWorkingFolder":
52 clean = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
53 break;
54 case "Codepage":
55 codepage = this.Core.GetAttributeCodePageValue(sourceLineNumbers, attrib);
56 break;
57 case "OutputPath":
58 outputPath = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
59 break;
60 case "SourceList":
61 sourceList = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
62 break;
63 case "SymbolFlags":
64 symbolFlags = String.Format(CultureInfo.InvariantCulture, "0x{0:x8}", this.Core.GetAttributeLongValue(sourceLineNumbers, attrib, 0, UInt32.MaxValue));
65 break;
66 case "WholeFilesOnly":
67 wholeFiles = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
68 break;
69 default:
70 this.Core.UnexpectedAttribute(node, attrib);
71 break;
72 }
73 }
74 else
75 {
76 this.Core.ParseExtensionAttribute(node, attrib);
77 }
78 }
79
80 if (null == this.activeName)
81 {
82 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
83 }
84
85 this.Core.CreateActiveSection(this.activeName, SectionType.PatchCreation, codepage, this.Context.CompilationId);
86
87 foreach (var child in node.Elements())
88 {
89 if (CompilerCore.WixNamespace == child.Name.Namespace)
90 {
91 switch (child.Name.LocalName)
92 {
93 case "Family":
94 this.ParseFamilyElement(child);
95 break;
96 case "PatchInformation":
97 this.ParsePatchInformationElement(child);
98 break;
99 case "PatchMetadata":
100 this.ParsePatchMetadataElement(child);
101 break;
102 case "PatchProperty":
103 this.ParsePatchPropertyElement(child, false);
104 break;
105 case "PatchSequence":
106 this.ParsePatchSequenceElement(child);
107 break;
108 case "ReplacePatch":
109 replaceGuids = String.Concat(replaceGuids, this.ParseReplacePatchElement(child));
110 break;
111 case "TargetProductCode":
112 var targetProduct = this.ParseTargetProductCodeElement(child);
113 if (0 < targetProducts.Length)
114 {
115 targetProducts = String.Concat(targetProducts, ";");
116 }
117 targetProducts = String.Concat(targetProducts, targetProduct);
118 break;
119 default:
120 this.Core.UnexpectedElement(node, child);
121 break;
122 }
123 }
124 else
125 {
126 this.Core.ParseExtensionElement(node, child);
127 }
128 }
129
130 this.AddPrivateProperty(sourceLineNumbers, "PatchGUID", this.activeName);
131 this.AddPrivateProperty(sourceLineNumbers, "AllowProductCodeMismatches", productMismatches ? "1" : "0");
132 this.AddPrivateProperty(sourceLineNumbers, "AllowProductVersionMajorMismatches", versionMismatches ? "1" : "0");
133 this.AddPrivateProperty(sourceLineNumbers, "DontRemoveTempFolderWhenFinished", clean ? "0" : "1");
134 this.AddPrivateProperty(sourceLineNumbers, "IncludeWholeFilesOnly", wholeFiles ? "1" : "0");
135
136 if (null != symbolFlags)
137 {
138 this.AddPrivateProperty(sourceLineNumbers, "ApiPatchingSymbolFlags", symbolFlags);
139 }
140
141 if (0 < replaceGuids.Length)
142 {
143 this.AddPrivateProperty(sourceLineNumbers, "ListOfPatchGUIDsToReplace", replaceGuids);
144 }
145
146 if (0 < targetProducts.Length)
147 {
148 this.AddPrivateProperty(sourceLineNumbers, "ListOfTargetProductCodes", targetProducts);
149 }
150
151 if (null != outputPath)
152 {
153 this.AddPrivateProperty(sourceLineNumbers, "PatchOutputPath", outputPath);
154 }
155
156 if (null != sourceList)
157 {
158 this.AddPrivateProperty(sourceLineNumbers, "PatchSourceList", sourceList);
159 }
160 }
161
162 /// <summary>
163 /// Parses a family element.
164 /// </summary>
165 /// <param name="node">The element to parse.</param>
166 private void ParseFamilyElement(XElement node)
167 {
168 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
169 var diskId = CompilerConstants.IntegerNotSet;
170 string diskPrompt = null;
171 string mediaSrcProp = null;
172 string name = null;
173 var sequenceStart = CompilerConstants.IntegerNotSet;
174 string volumeLabel = null;
175
176 foreach (var attrib in node.Attributes())
177 {
178 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
179 {
180 switch (attrib.Name.LocalName)
181 {
182 case "DiskId":
183 diskId = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, Int16.MaxValue);
184 break;
185 case "DiskPrompt":
186 diskPrompt = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
187 break;
188 case "MediaSrcProp":
189 mediaSrcProp = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
190 break;
191 case "Name":
192 name = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
193 break;
194 case "SequenceStart":
195 sequenceStart = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, Int32.MaxValue);
196 break;
197 case "VolumeLabel":
198 volumeLabel = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
199 break;
200 default:
201 this.Core.UnexpectedAttribute(node, attrib);
202 break;
203 }
204 }
205 else
206 {
207 this.Core.ParseExtensionAttribute(node, attrib);
208 }
209 }
210
211 if (null == name)
212 {
213 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Name"));
214 }
215 else if (0 < name.Length)
216 {
217 if (8 < name.Length) // check the length
218 {
219 this.Core.Write(ErrorMessages.FamilyNameTooLong(sourceLineNumbers, node.Name.LocalName, "Name", name, name.Length));
220 }
221 else // check for illegal characters
222 {
223 foreach (var character in name)
224 {
225 if (!Char.IsLetterOrDigit(character) && '_' != character)
226 {
227 this.Core.Write(ErrorMessages.IllegalFamilyName(sourceLineNumbers, node.Name.LocalName, "Name", name));
228 }
229 }
230 }
231 }
232
233 foreach (var child in node.Elements())
234 {
235 if (CompilerCore.WixNamespace == child.Name.Namespace)
236 {
237 switch (child.Name.LocalName)
238 {
239 case "UpgradeImage":
240 this.ParseUpgradeImageElement(child, name);
241 break;
242 case "ExternalFile":
243 this.ParseExternalFileElement(child, name);
244 break;
245 case "ProtectFile":
246 this.ParseProtectFileElement(child, name);
247 break;
248 default:
249 this.Core.UnexpectedElement(node, child);
250 break;
251 }
252 }
253 else
254 {
255 this.Core.ParseExtensionElement(node, child);
256 }
257 }
258
259 if (!this.Core.EncounteredError)
260 {
261 var tuple = new ImageFamiliesTuple(sourceLineNumbers)
262 {
263 Family = name,
264 MediaSrcPropName = mediaSrcProp,
265 DiskPrompt = diskPrompt,
266 VolumeLabel = volumeLabel
267 };
268
269 if (CompilerConstants.IntegerNotSet != diskId)
270 {
271 tuple.MediaDiskId = diskId;
272 }
273
274 if (CompilerConstants.IntegerNotSet != sequenceStart)
275 {
276 tuple.FileSequenceStart = sequenceStart;
277 }
278
279 this.Core.AddTuple(tuple);
280 }
281 }
282
283 /// <summary>
284 /// Parses an upgrade image element.
285 /// </summary>
286 /// <param name="node">The element to parse.</param>
287 /// <param name="family">The family for this element.</param>
288 private void ParseUpgradeImageElement(XElement node, string family)
289 {
290 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
291 string sourceFile = null;
292 string sourcePatch = null;
293 var symbols = new List<string>();
294 string upgrade = null;
295
296 foreach (var attrib in node.Attributes())
297 {
298 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
299 {
300 switch (attrib.Name.LocalName)
301 {
302 case "Id":
303 upgrade = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
304 if (13 < upgrade.Length)
305 {
306 this.Core.Write(ErrorMessages.IdentifierTooLongError(sourceLineNumbers, node.Name.LocalName, "Id", upgrade, 13));
307 }
308 break;
309 case "SourceFile":
310 case "src":
311 if (null != sourceFile)
312 {
313 this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, "src", "SourceFile"));
314 }
315
316 if ("src" == attrib.Name.LocalName)
317 {
318 this.Core.Write(WarningMessages.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "SourceFile"));
319 }
320 sourceFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
321 break;
322 case "SourcePatch":
323 case "srcPatch":
324 if (null != sourcePatch)
325 {
326 this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, "srcPatch", "SourcePatch"));
327 }
328
329 if ("srcPatch" == attrib.Name.LocalName)
330 {
331 this.Core.Write(WarningMessages.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "SourcePatch"));
332 }
333 sourcePatch = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
334 break;
335 default:
336 this.Core.UnexpectedAttribute(node, attrib);
337 break;
338 }
339 }
340 else
341 {
342 this.Core.ParseExtensionAttribute(node, attrib);
343 }
344 }
345
346 if (null == upgrade)
347 {
348 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
349 }
350
351 if (null == sourceFile)
352 {
353 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "SourceFile"));
354 }
355
356 foreach (var child in node.Elements())
357 {
358 if (CompilerCore.WixNamespace == child.Name.Namespace)
359 {
360 switch (child.Name.LocalName)
361 {
362 case "SymbolPath":
363 symbols.Add(this.ParseSymbolPathElement(child));
364 break;
365 case "TargetImage":
366 this.ParseTargetImageElement(child, upgrade, family);
367 break;
368 case "UpgradeFile":
369 this.ParseUpgradeFileElement(child, upgrade);
370 break;
371 default:
372 this.Core.UnexpectedElement(node, child);
373 break;
374 }
375 }
376 else
377 {
378 this.Core.ParseExtensionElement(node, child);
379 }
380 }
381
382 if (!this.Core.EncounteredError)
383 {
384 this.Core.AddTuple(new UpgradedImagesTuple(sourceLineNumbers)
385 {
386 Upgraded = upgrade,
387 MsiPath = sourceFile,
388 PatchMsiPath = sourcePatch,
389 SymbolPaths = String.Join(";", symbols),
390 Family = family
391 });
392 }
393 }
394
395 /// <summary>
396 /// Parses an upgrade file element.
397 /// </summary>
398 /// <param name="node">The element to parse.</param>
399 /// <param name="upgrade">The upgrade key for this element.</param>
400 private void ParseUpgradeFileElement(XElement node, string upgrade)
401 {
402 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
403 var allowIgnoreOnError = false;
404 string file = null;
405 var ignore = false;
406 var symbols = new List<string>();
407 var wholeFile = false;
408
409 foreach (var attrib in node.Attributes())
410 {
411 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
412 {
413 switch (attrib.Name.LocalName)
414 {
415 case "AllowIgnoreOnError":
416 allowIgnoreOnError = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
417 break;
418 case "File":
419 file = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
420 break;
421 case "Ignore":
422 ignore = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
423 break;
424 case "WholeFile":
425 wholeFile = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
426 break;
427 default:
428 this.Core.UnexpectedAttribute(node, attrib);
429 break;
430 }
431 }
432 else
433 {
434 this.Core.ParseExtensionAttribute(node, attrib);
435 }
436 }
437
438 if (null == file)
439 {
440 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "File"));
441 }
442
443 foreach (var child in node.Elements())
444 {
445 if (CompilerCore.WixNamespace == child.Name.Namespace)
446 {
447 switch (child.Name.LocalName)
448 {
449 case "SymbolPath":
450 symbols.Add(this.ParseSymbolPathElement(child));
451 break;
452 default:
453 this.Core.UnexpectedElement(node, child);
454 break;
455 }
456 }
457 else
458 {
459 this.Core.ParseExtensionElement(node, child);
460 }
461 }
462
463 if (!this.Core.EncounteredError)
464 {
465 if (ignore)
466 {
467 this.Core.AddTuple(new UpgradedFilesToIgnoreTuple(sourceLineNumbers)
468 {
469 Upgraded = upgrade,
470 FTK = file
471 });
472 }
473 else
474 {
475 this.Core.AddTuple(new UpgradedFiles_OptionalDataTuple(sourceLineNumbers)
476 {
477 Upgraded = upgrade,
478 FTK = file,
479 SymbolPaths = String.Join(";", symbols),
480 AllowIgnoreOnPatchError = allowIgnoreOnError,
481 IncludeWholeFile = wholeFile
482 });
483 }
484 }
485 }
486
487 /// <summary>
488 /// Parses a target image element.
489 /// </summary>
490 /// <param name="node">The element to parse.</param>
491 /// <param name="upgrade">The upgrade key for this element.</param>
492 /// <param name="family">The family key for this element.</param>
493 private void ParseTargetImageElement(XElement node, string upgrade, string family)
494 {
495 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
496 var ignore = false;
497 var order = CompilerConstants.IntegerNotSet;
498 string sourceFile = null;
499 string symbols = null;
500 string target = null;
501 string validation = null;
502
503 foreach (var attrib in node.Attributes())
504 {
505 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
506 {
507 switch (attrib.Name.LocalName)
508 {
509 case "Id":
510 target = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
511 if (target.Length > 13)
512 {
513 this.Core.Write(ErrorMessages.IdentifierTooLongError(sourceLineNumbers, node.Name.LocalName, "Id", target, 13));
514 }
515 break;
516 case "IgnoreMissingFiles":
517 ignore = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
518 break;
519 case "Order":
520 order = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, Int32.MinValue + 2, Int32.MaxValue);
521 break;
522 case "SourceFile":
523 case "src":
524 if (null != sourceFile)
525 {
526 this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, "src", "SourceFile"));
527 }
528
529 if ("src" == attrib.Name.LocalName)
530 {
531 this.Core.Write(WarningMessages.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "SourceFile"));
532 }
533 sourceFile = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
534 break;
535 case "Validation":
536 validation = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
537 break;
538 default:
539 this.Core.UnexpectedAttribute(node, attrib);
540 break;
541 }
542 }
543 else
544 {
545 this.Core.ParseExtensionAttribute(node, attrib);
546 }
547 }
548
549 if (null == target)
550 {
551 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
552 }
553
554 if (null == sourceFile)
555 {
556 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "SourceFile"));
557 }
558
559 if (CompilerConstants.IntegerNotSet == order)
560 {
561 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Order"));
562 }
563
564 foreach (var child in node.Elements())
565 {
566 if (CompilerCore.WixNamespace == child.Name.Namespace)
567 {
568 switch (child.Name.LocalName)
569 {
570 case "SymbolPath":
571 if (null != symbols)
572 {
573 symbols = String.Concat(symbols, ";", this.ParseSymbolPathElement(child));
574 }
575 else
576 {
577 symbols = this.ParseSymbolPathElement(child);
578 }
579 break;
580 case "TargetFile":
581 this.ParseTargetFileElement(child, target, family);
582 break;
583 default:
584 this.Core.UnexpectedElement(node, child);
585 break;
586 }
587 }
588 else
589 {
590 this.Core.ParseExtensionElement(node, child);
591 }
592 }
593
594 if (!this.Core.EncounteredError)
595 {
596 this.Core.AddTuple(new TargetImagesTuple(sourceLineNumbers)
597 {
598 Target = target,
599 MsiPath = sourceFile,
600 SymbolPaths = symbols,
601 Upgraded = upgrade,
602 Order = order,
603 ProductValidateFlags = validation,
604 IgnoreMissingSrcFiles = ignore
605 });
606 }
607 }
608
609 /// <summary>
610 /// Parses an upgrade file element.
611 /// </summary>
612 /// <param name="node">The element to parse.</param>
613 /// <param name="target">The upgrade key for this element.</param>
614 /// <param name="family">The family key for this element.</param>
615 private void ParseTargetFileElement(XElement node, string target, string family)
616 {
617 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
618 string file = null;
619 string ignoreLengths = null;
620 string ignoreOffsets = null;
621 string protectLengths = null;
622 string protectOffsets = null;
623 string symbols = null;
624
625 foreach (var attrib in node.Attributes())
626 {
627 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
628 {
629 switch (attrib.Name.LocalName)
630 {
631 case "Id":
632 file = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
633 break;
634 default:
635 this.Core.UnexpectedAttribute(node, attrib);
636 break;
637 }
638 }
639 else
640 {
641 this.Core.ParseExtensionAttribute(node, attrib);
642 }
643 }
644
645 if (null == file)
646 {
647 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
648 }
649
650 foreach (var child in node.Elements())
651 {
652 if (CompilerCore.WixNamespace == child.Name.Namespace)
653 {
654 switch (child.Name.LocalName)
655 {
656 case "IgnoreRange":
657 this.ParseRangeElement(child, ref ignoreOffsets, ref ignoreLengths);
658 break;
659 case "ProtectRange":
660 this.ParseRangeElement(child, ref protectOffsets, ref protectLengths);
661 break;
662 case "SymbolPath":
663 symbols = this.ParseSymbolPathElement(child);
664 break;
665 default:
666 this.Core.UnexpectedElement(node, child);
667 break;
668 }
669 }
670 else
671 {
672 this.Core.ParseExtensionElement(node, child);
673 }
674 }
675
676 if (!this.Core.EncounteredError)
677 {
678 var tuple = new TargetFiles_OptionalDataTuple(sourceLineNumbers)
679 {
680 Target = target,
681 FTK = file,
682 SymbolPaths = symbols,
683 IgnoreOffsets = ignoreOffsets,
684 IgnoreLengths = ignoreLengths
685 };
686
687 this.Core.AddTuple(tuple);
688
689 if (null != protectOffsets)
690 {
691 tuple.RetainOffsets = protectOffsets;
692
693 this.Core.AddTuple(new FamilyFileRangesTuple(sourceLineNumbers)
694 {
695 Family = family,
696 FTK = file,
697 RetainOffsets = protectOffsets,
698 RetainLengths = protectLengths
699 });
700 }
701 }
702 }
703
704 /// <summary>
705 /// Parses an external file element.
706 /// </summary>
707 /// <param name="node">The element to parse.</param>
708 /// <param name="family">The family for this element.</param>
709 private void ParseExternalFileElement(XElement node, string family)
710 {
711 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
712 string file = null;
713 string ignoreLengths = null;
714 string ignoreOffsets = null;
715 var order = CompilerConstants.IntegerNotSet;
716 string protectLengths = null;
717 string protectOffsets = null;
718 string source = null;
719 string symbols = null;
720
721 foreach (var attrib in node.Attributes())
722 {
723 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
724 {
725 switch (attrib.Name.LocalName)
726 {
727 case "File":
728 file = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
729 break;
730 case "Order":
731 order = this.Core.GetAttributeIntegerValue(sourceLineNumbers, attrib, Int32.MinValue + 2, Int32.MaxValue);
732 break;
733 case "Source":
734 case "src":
735 if (null != source)
736 {
737 this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, "src", "Source"));
738 }
739
740 if ("src" == attrib.Name.LocalName)
741 {
742 this.Core.Write(WarningMessages.DeprecatedAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "Source"));
743 }
744 source = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
745 break;
746 default:
747 this.Core.UnexpectedAttribute(node, attrib);
748 break;
749 }
750 }
751 else
752 {
753 this.Core.ParseExtensionAttribute(node, attrib);
754 }
755 }
756
757 if (null == file)
758 {
759 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "File"));
760 }
761
762 if (null == source)
763 {
764 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Source"));
765 }
766
767 if (CompilerConstants.IntegerNotSet == order)
768 {
769 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Order"));
770 }
771
772 foreach (var child in node.Elements())
773 {
774 if (CompilerCore.WixNamespace == child.Name.Namespace)
775 {
776 switch (child.Name.LocalName)
777 {
778 case "IgnoreRange":
779 this.ParseRangeElement(child, ref ignoreOffsets, ref ignoreLengths);
780 break;
781 case "ProtectRange":
782 this.ParseRangeElement(child, ref protectOffsets, ref protectLengths);
783 break;
784 case "SymbolPath":
785 symbols = this.ParseSymbolPathElement(child);
786 break;
787 default:
788 this.Core.UnexpectedElement(node, child);
789 break;
790 }
791 }
792 else
793 {
794 this.Core.ParseExtensionElement(node, child);
795 }
796 }
797
798 if (!this.Core.EncounteredError)
799 {
800 var tuple = new ExternalFilesTuple(sourceLineNumbers)
801 {
802 Family = family,
803 FTK = file,
804 FilePath = source,
805 SymbolPaths = symbols,
806 IgnoreOffsets = ignoreOffsets,
807 IgnoreLengths = ignoreLengths
808 };
809
810 if (null != protectOffsets)
811 {
812 tuple.RetainOffsets = protectOffsets;
813 }
814
815 if (CompilerConstants.IntegerNotSet != order)
816 {
817 tuple.Order = order;
818 }
819
820 this.Core.AddTuple(tuple);
821
822 if (null != protectOffsets)
823 {
824 this.Core.AddTuple(new FamilyFileRangesTuple(sourceLineNumbers)
825 {
826 Family = family,
827 FTK = file,
828 RetainOffsets = protectOffsets,
829 RetainLengths = protectLengths
830 });
831 }
832 }
833 }
834
835 /// <summary>
836 /// Parses a protect file element.
837 /// </summary>
838 /// <param name="node">The element to parse.</param>
839 /// <param name="family">The family for this element.</param>
840 private void ParseProtectFileElement(XElement node, string family)
841 {
842 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
843 string file = null;
844 string protectLengths = null;
845 string protectOffsets = null;
846
847 foreach (var attrib in node.Attributes())
848 {
849 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
850 {
851 switch (attrib.Name.LocalName)
852 {
853 case "File":
854 file = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
855 break;
856 default:
857 this.Core.UnexpectedAttribute(node, attrib);
858 break;
859 }
860 }
861 else
862 {
863 this.Core.ParseExtensionAttribute(node, attrib);
864 }
865 }
866
867 if (null == file)
868 {
869 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "File"));
870 }
871
872 foreach (var child in node.Elements())
873 {
874 if (CompilerCore.WixNamespace == child.Name.Namespace)
875 {
876 switch (child.Name.LocalName)
877 {
878 case "ProtectRange":
879 this.ParseRangeElement(child, ref protectOffsets, ref protectLengths);
880 break;
881 default:
882 this.Core.UnexpectedElement(node, child);
883 break;
884 }
885 }
886 else
887 {
888 this.Core.ParseExtensionElement(node, child);
889 }
890 }
891
892 if (null == protectOffsets || null == protectLengths)
893 {
894 this.Core.Write(ErrorMessages.ExpectedElement(sourceLineNumbers, node.Name.LocalName, "ProtectRange"));
895 }
896
897 if (!this.Core.EncounteredError)
898 {
899 this.Core.AddTuple(new FamilyFileRangesTuple(sourceLineNumbers)
900 {
901 Family = family,
902 FTK = file,
903 RetainOffsets = protectOffsets,
904 RetainLengths = protectLengths
905 });
906 }
907 }
908
909 /// <summary>
910 /// Parses a range element (ProtectRange, IgnoreRange, etc).
911 /// </summary>
912 /// <param name="node">The element to parse.</param>
913 /// <param name="offsets">Reference to the offsets string.</param>
914 /// <param name="lengths">Reference to the lengths string.</param>
915 private void ParseRangeElement(XElement node, ref string offsets, ref string lengths)
916 {
917 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
918 string length = null;
919 string offset = null;
920
921 foreach (var attrib in node.Attributes())
922 {
923 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
924 {
925 switch (attrib.Name.LocalName)
926 {
927 case "Length":
928 length = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
929 break;
930 case "Offset":
931 offset = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
932 break;
933 default:
934 this.Core.UnexpectedAttribute(node, attrib);
935 break;
936 }
937 }
938 else
939 {
940 this.Core.ParseExtensionAttribute(node, attrib);
941 }
942 }
943
944 if (null == length)
945 {
946 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Length"));
947 }
948
949 if (null == offset)
950 {
951 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Offset"));
952 }
953
954 this.Core.ParseForExtensionElements(node);
955
956 if (null != lengths)
957 {
958 lengths = String.Concat(lengths, ",", length);
959 }
960 else
961 {
962 lengths = length;
963 }
964
965 if (null != offsets)
966 {
967 offsets = String.Concat(offsets, ",", offset);
968 }
969 else
970 {
971 offsets = offset;
972 }
973 }
974
975 /// <summary>
976 /// Parses a patch metadata element.
977 /// </summary>
978 /// <param name="node">Element to parse.</param>
979 private void ParsePatchMetadataElement(XElement node)
980 {
981 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
982 var allowRemoval = YesNoType.NotSet;
983 string classification = null;
984 string creationTimeUtc = null;
985 string description = null;
986 string displayName = null;
987 string manufacturerName = null;
988 string minorUpdateTargetRTM = null;
989 string moreInfoUrl = null;
990 var optimizeCA = CompilerConstants.IntegerNotSet;
991 var optimizedInstallMode = YesNoType.NotSet;
992 string targetProductName = null;
993
994 foreach (var attrib in node.Attributes())
995 {
996 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
997 {
998 switch (attrib.Name.LocalName)
999 {
1000 case "AllowRemoval":
1001 allowRemoval = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
1002 break;
1003 case "Classification":
1004 classification = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1005 break;
1006 case "CreationTimeUTC":
1007 creationTimeUtc = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1008 break;
1009 case "Description":
1010 description = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1011 break;
1012 case "DisplayName":
1013 displayName = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1014 break;
1015 case "ManufacturerName":
1016 manufacturerName = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1017 break;
1018 case "MinorUpdateTargetRTM":
1019 minorUpdateTargetRTM = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1020 break;
1021 case "MoreInfoURL":
1022 moreInfoUrl = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1023 break;
1024 case "OptimizedInstallMode":
1025 optimizedInstallMode = this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
1026 break;
1027 case "TargetProductName":
1028 targetProductName = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1029 break;
1030 default:
1031 this.Core.UnexpectedAttribute(node, attrib);
1032 break;
1033 }
1034 }
1035 else
1036 {
1037 this.Core.ParseExtensionAttribute(node, attrib);
1038 }
1039 }
1040
1041 if (YesNoType.NotSet == allowRemoval)
1042 {
1043 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "AllowRemoval"));
1044 }
1045
1046 if (null == classification)
1047 {
1048 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Classification"));
1049 }
1050
1051 if (null == description)
1052 {
1053 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Description"));
1054 }
1055
1056 if (null == displayName)
1057 {
1058 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "DisplayName"));
1059 }
1060
1061 if (null == manufacturerName)
1062 {
1063 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "ManufacturerName"));
1064 }
1065
1066 if (null == moreInfoUrl)
1067 {
1068 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "MoreInfoURL"));
1069 }
1070
1071 if (null == targetProductName)
1072 {
1073 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "TargetProductName"));
1074 }
1075
1076 foreach (var child in node.Elements())
1077 {
1078 if (CompilerCore.WixNamespace == child.Name.Namespace)
1079 {
1080 switch (child.Name.LocalName)
1081 {
1082 case "CustomProperty":
1083 this.ParseCustomPropertyElement(child);
1084 break;
1085 case "OptimizeCustomActions":
1086 optimizeCA = this.ParseOptimizeCustomActionsElement(child);
1087 break;
1088 default:
1089 this.Core.UnexpectedElement(node, child);
1090 break;
1091 }
1092 }
1093 else
1094 {
1095 this.Core.ParseExtensionElement(node, child);
1096 }
1097 }
1098
1099 if (!this.Core.EncounteredError)
1100 {
1101 if (YesNoType.NotSet != allowRemoval)
1102 {
1103 this.AddPatchMetadata(sourceLineNumbers, null, "AllowRemoval", YesNoType.Yes == allowRemoval ? "1" : "0");
1104 }
1105
1106 if (null != classification)
1107 {
1108 this.AddPatchMetadata(sourceLineNumbers, null, "Classification", classification);
1109 }
1110
1111 if (null != creationTimeUtc)
1112 {
1113 this.AddPatchMetadata(sourceLineNumbers, null, "CreationTimeUTC", creationTimeUtc);
1114 }
1115
1116 if (null != description)
1117 {
1118 this.AddPatchMetadata(sourceLineNumbers, null, "Description", description);
1119 }
1120
1121 if (null != displayName)
1122 {
1123 this.AddPatchMetadata(sourceLineNumbers, null, "DisplayName", displayName);
1124 }
1125
1126 if (null != manufacturerName)
1127 {
1128 this.AddPatchMetadata(sourceLineNumbers, null, "ManufacturerName", manufacturerName);
1129 }
1130
1131 if (null != minorUpdateTargetRTM)
1132 {
1133 this.AddPatchMetadata(sourceLineNumbers, null, "MinorUpdateTargetRTM", minorUpdateTargetRTM);
1134 }
1135
1136 if (null != moreInfoUrl)
1137 {
1138 this.AddPatchMetadata(sourceLineNumbers, null, "MoreInfoURL", moreInfoUrl);
1139 }
1140
1141 if (CompilerConstants.IntegerNotSet != optimizeCA)
1142 {
1143 this.AddPatchMetadata(sourceLineNumbers, null, "OptimizeCA", optimizeCA.ToString(CultureInfo.InvariantCulture));
1144 }
1145
1146 if (YesNoType.NotSet != optimizedInstallMode)
1147 {
1148 this.AddPatchMetadata(sourceLineNumbers, null, "OptimizedInstallMode", YesNoType.Yes == optimizedInstallMode ? "1" : "0");
1149 }
1150
1151 if (null != targetProductName)
1152 {
1153 this.AddPatchMetadata(sourceLineNumbers, null, "TargetProductName", targetProductName);
1154 }
1155 }
1156 }
1157
1158 /// <summary>
1159 /// Parses a custom property element for the PatchMetadata table.
1160 /// </summary>
1161 /// <param name="node">Element to parse.</param>
1162 private void ParseCustomPropertyElement(XElement node)
1163 {
1164 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
1165 string company = null;
1166 string property = null;
1167 string value = null;
1168
1169 foreach (var attrib in node.Attributes())
1170 {
1171 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
1172 {
1173 switch (attrib.Name.LocalName)
1174 {
1175 case "Company":
1176 company = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1177 break;
1178 case "Property":
1179 property = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1180 break;
1181 case "Value":
1182 value = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1183 break;
1184 default:
1185 this.Core.UnexpectedAttribute(node, attrib);
1186 break;
1187 }
1188 }
1189 else
1190 {
1191 this.Core.ParseExtensionAttribute(node, attrib);
1192 }
1193 }
1194
1195 if (null == company)
1196 {
1197 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Company"));
1198 }
1199
1200 if (null == property)
1201 {
1202 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Property"));
1203 }
1204
1205 if (null == value)
1206 {
1207 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Value"));
1208 }
1209
1210 this.Core.ParseForExtensionElements(node);
1211
1212 if (!this.Core.EncounteredError)
1213 {
1214 this.AddPatchMetadata(sourceLineNumbers, company, property, value);
1215 }
1216 }
1217
1218 /// <summary>
1219 /// Parses a patch sequence element.
1220 /// </summary>
1221 /// <param name="node">The element to parse.</param>
1222 private void ParsePatchSequenceElement(XElement node)
1223 {
1224 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
1225 string family = null;
1226 string target = null;
1227 string sequence = null;
1228 var attributes = 0;
1229
1230 foreach (var attrib in node.Attributes())
1231 {
1232 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
1233 {
1234 switch (attrib.Name.LocalName)
1235 {
1236 case "PatchFamily":
1237 family = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
1238 break;
1239 case "ProductCode":
1240 if (null != target)
1241 {
1242 this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "Target", "TargetImage"));
1243 }
1244 target = this.Core.GetAttributeGuidValue(sourceLineNumbers, attrib, false);
1245 break;
1246 case "Target":
1247 if (null != target)
1248 {
1249 this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "TargetImage", "ProductCode"));
1250 }
1251 this.Core.Write(WarningMessages.DeprecatedPatchSequenceTargetAttribute(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName));
1252 target = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1253 break;
1254 case "TargetImage":
1255 if (null != target)
1256 {
1257 this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttributes(sourceLineNumbers, node.Name.LocalName, attrib.Name.LocalName, "Target", "ProductCode"));
1258 }
1259 target = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
1260 this.Core.CreateSimpleReference(sourceLineNumbers, "TargetImages", target);
1261 break;
1262 case "Sequence":
1263 sequence = this.Core.GetAttributeVersionValue(sourceLineNumbers, attrib);
1264 break;
1265 case "Supersede":
1266 if (YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib))
1267 {
1268 attributes |= 0x1;
1269 }
1270 break;
1271 default:
1272 this.Core.UnexpectedAttribute(node, attrib);
1273 break;
1274 }
1275 }
1276 else
1277 {
1278 this.Core.ParseExtensionAttribute(node, attrib);
1279 }
1280 }
1281
1282 if (null == family)
1283 {
1284 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "PatchFamily"));
1285 }
1286
1287 this.Core.ParseForExtensionElements(node);
1288
1289 if (!this.Core.EncounteredError)
1290 {
1291 var tuple = new PatchSequenceTuple(sourceLineNumbers)
1292 {
1293 PatchFamily = family,
1294 Target = target,
1295 Sequence = sequence,
1296 Supersede = attributes
1297 };
1298
1299 this.Core.AddTuple(tuple);
1300 }
1301 }
1302
1303 private void AddPatchMetadata(SourceLineNumber sourceLineNumbers, string company, string property, string value)
1304 {
1305 this.Core.AddTuple(new PatchMetadataTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, company, property))
1306 {
1307 Company = company,
1308 Property = property,
1309 Value = value
1310 });
1311 }
1312 }
1313}
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
120 120
121 // the following are available indentically under the UI and Product elements for document organization use only 121 // the following are available indentically under the UI and Product elements for document organization use only
122 case "AdminUISequence": 122 case "AdminUISequence":
123 this.ParseSequenceElement(child, SequenceTable.AdminUISequence);
124 break;
123 case "InstallUISequence": 125 case "InstallUISequence":
124 this.ParseSequenceElement(child, child.Name.LocalName); 126 this.ParseSequenceElement(child, SequenceTable.InstallUISequence);
125 break; 127 break;
126 case "Binary": 128 case "Binary":
127 this.ParseBinaryElement(child); 129 this.ParseBinaryElement(child);
@@ -149,7 +151,8 @@ namespace WixToolset.Core
149 151
150 if (null != id && !this.Core.EncounteredError) 152 if (null != id && !this.Core.EncounteredError)
151 { 153 {
152 this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.WixUI, id); 154 var tuple = new WixUITuple(sourceLineNumbers, id);
155 this.Core.AddTuple(tuple);
153 } 156 }
154 } 157 }
155 158
@@ -160,7 +163,7 @@ namespace WixToolset.Core
160 /// <param name="table">Table to add row to.</param> 163 /// <param name="table">Table to add row to.</param>
161 /// <param name="property">Identifier of property referred to by list item.</param> 164 /// <param name="property">Identifier of property referred to by list item.</param>
162 /// <param name="order">Relative order of list items.</param> 165 /// <param name="order">Relative order of list items.</param>
163 private void ParseListItemElement(XElement node, TupleDefinitionType tableName, string property, ref int order) 166 private void ParseListItemElement(XElement node, TupleDefinitionType tupleType, string property, ref int order)
164 { 167 {
165 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); 168 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
166 string icon = null; 169 string icon = null;
@@ -174,7 +177,7 @@ namespace WixToolset.Core
174 switch (attrib.Name.LocalName) 177 switch (attrib.Name.LocalName)
175 { 178 {
176 case "Icon": 179 case "Icon":
177 if (TupleDefinitionType.ListView == tableName) 180 if (TupleDefinitionType.ListView == tupleType)
178 { 181 {
179 icon = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); 182 icon = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
180 this.Core.CreateSimpleReference(sourceLineNumbers, "Binary", icon); 183 this.Core.CreateSimpleReference(sourceLineNumbers, "Binary", icon);
@@ -210,14 +213,14 @@ namespace WixToolset.Core
210 213
211 if (!this.Core.EncounteredError) 214 if (!this.Core.EncounteredError)
212 { 215 {
213 var row = this.Core.CreateRow(sourceLineNumbers, tableName); 216 var tuple = this.Core.CreateTuple(sourceLineNumbers, tupleType);
214 row.Set(0, property); 217 tuple.Set(0, property);
215 row.Set(1, ++order); 218 tuple.Set(1, ++order);
216 row.Set(2, value); 219 tuple.Set(2, value);
217 row.Set(3, text); 220 tuple.Set(3, text);
218 if (null != icon) 221 if (null != icon)
219 { 222 {
220 row.Set(4, icon); 223 tuple.Set(4, icon);
221 } 224 }
222 } 225 }
223 } 226 }
@@ -335,19 +338,21 @@ namespace WixToolset.Core
335 338
336 if (!this.Core.EncounteredError) 339 if (!this.Core.EncounteredError)
337 { 340 {
338 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.RadioButton); 341 var tuple = new RadioButtonTuple(sourceLineNumbers)
339 row.Set(0, property);
340 row.Set(1, ++order);
341 row.Set(2, value);
342 row.Set(3, x);
343 row.Set(4, y);
344 row.Set(5, width);
345 row.Set(6, height);
346 row.Set(7, text);
347 if (null != tooltip || null != help)
348 { 342 {
349 row.Set(8, String.Concat(tooltip, "|", help)); 343 Property = property,
350 } 344 Order = ++order,
345 Value = value,
346 Text = text,
347 Help = (null != tooltip || null != help) ? String.Concat(tooltip, "|", help) : null
348 };
349
350 tuple.Set((int)RadioButtonTupleFields.X, x);
351 tuple.Set((int)RadioButtonTupleFields.Y, y);
352 tuple.Set((int)RadioButtonTupleFields.Width, width);
353 tuple.Set((int)RadioButtonTupleFields.Height, height);
354
355 this.Core.AddTuple(tuple);
351 } 356 }
352 357
353 return type; 358 return type;
@@ -481,10 +486,14 @@ namespace WixToolset.Core
481 486
482 if (!this.Core.EncounteredError) 487 if (!this.Core.EncounteredError)
483 { 488 {
484 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.Billboard, id); 489 var tuple = new BillboardTuple(sourceLineNumbers, id)
485 row.Set(1, feature); 490 {
486 row.Set(2, action); 491 Feature_ = feature,
487 row.Set(3, order); 492 Action = action,
493 Ordering = order
494 };
495
496 this.Core.AddTuple(tuple);
488 } 497 }
489 } 498 }
490 499
@@ -494,7 +503,7 @@ namespace WixToolset.Core
494 /// <param name="node">Element to parse.</param> 503 /// <param name="node">Element to parse.</param>
495 /// <param name="table">Table referred to by control group.</param> 504 /// <param name="table">Table referred to by control group.</param>
496 /// <param name="childTag">Expected child elements.</param> 505 /// <param name="childTag">Expected child elements.</param>
497 private void ParseControlGroupElement(XElement node, TupleDefinitionType tableName, string childTag) 506 private void ParseControlGroupElement(XElement node, TupleDefinitionType tupleType, string childTag)
498 { 507 {
499 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); 508 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
500 var order = 0; 509 var order = 0;
@@ -537,7 +546,7 @@ namespace WixToolset.Core
537 switch (child.Name.LocalName) 546 switch (child.Name.LocalName)
538 { 547 {
539 case "ListItem": 548 case "ListItem":
540 this.ParseListItemElement(child, tableName, property, ref order); 549 this.ParseListItemElement(child, tupleType, property, ref order);
541 break; 550 break;
542 case "Property": 551 case "Property":
543 this.ParsePropertyElement(child); 552 this.ParsePropertyElement(child);
@@ -668,10 +677,14 @@ namespace WixToolset.Core
668 677
669 if (!this.Core.EncounteredError) 678 if (!this.Core.EncounteredError)
670 { 679 {
671 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ActionText); 680 var tuple = new ActionTextTuple(sourceLineNumbers)
672 row.Set(0, action); 681 {
673 row.Set(1, Common.GetInnerText(node)); 682 Action = action,
674 row.Set(2, template); 683 Description = Common.GetInnerText(node),
684 Template = template
685 };
686
687 this.Core.AddTuple(tuple);
675 } 688 }
676 } 689 }
677 690
@@ -716,8 +729,12 @@ namespace WixToolset.Core
716 729
717 if (!this.Core.EncounteredError) 730 if (!this.Core.EncounteredError)
718 { 731 {
719 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.UIText, id); 732 var tuple = new UITextTuple(sourceLineNumbers, id)
720 row.Set(1, text); 733 {
734 Text = text,
735 };
736
737 this.Core.AddTuple(tuple);
721 } 738 }
722 } 739 }
723 740
@@ -1654,13 +1671,17 @@ namespace WixToolset.Core
1654 1671
1655 if (!this.Core.EncounteredError) 1672 if (!this.Core.EncounteredError)
1656 { 1673 {
1657 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.ControlEvent); 1674 var tuple = new ControlEventTuple(sourceLineNumbers)
1658 row.Set(0, dialog); 1675 {
1659 row.Set(1, control); 1676 Dialog_ = dialog,
1660 row.Set(2, (null != controlEvent ? controlEvent : property)); 1677 Control_ = control,
1661 row.Set(3, argument); 1678 Event = controlEvent ?? property,
1662 row.Set(4, condition); 1679 Argument = argument,
1663 row.Set(5, order); 1680 Condition = condition,
1681 Ordering = order
1682 };
1683
1684 this.Core.AddTuple(tuple);
1664 } 1685 }
1665 1686
1666 if ("DoAction" == controlEvent && null != argument) 1687 if ("DoAction" == controlEvent && null != argument)
@@ -1719,11 +1740,15 @@ namespace WixToolset.Core
1719 1740
1720 if (!this.Core.EncounteredError) 1741 if (!this.Core.EncounteredError)
1721 { 1742 {
1722 var row = this.Core.CreateRow(sourceLineNumbers, TupleDefinitionType.EventMapping); 1743 var tuple = new EventMappingTuple(sourceLineNumbers)
1723 row.Set(0, dialog); 1744 {
1724 row.Set(1, control); 1745 Dialog_ = dialog,
1725 row.Set(2, eventMapping); 1746 Control_ = control,
1726 row.Set(3, controlAttribute); 1747 Event = eventMapping,
1748 Attribute = controlAttribute
1749 }; ;
1750
1751 this.Core.AddTuple(tuple);
1727 } 1752 }
1728 } 1753 }
1729 } 1754 }
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,19 +53,30 @@ namespace WixToolset.Core.ExtensibilityServices
53 53
54 public void CreateComplexReference(IntermediateSection section, SourceLineNumber sourceLineNumbers, ComplexReferenceParentType parentType, string parentId, string parentLanguage, ComplexReferenceChildType childType, string childId, bool isPrimary) 54 public void CreateComplexReference(IntermediateSection section, SourceLineNumber sourceLineNumbers, ComplexReferenceParentType parentType, string parentId, string parentLanguage, ComplexReferenceChildType childType, string childId, bool isPrimary)
55 { 55 {
56 var wixComplexReferenceRow = (WixComplexReferenceTuple)this.CreateRow(section, sourceLineNumbers, TupleDefinitionType.WixComplexReference);
57 wixComplexReferenceRow.Parent = parentId;
58 wixComplexReferenceRow.ParentType = parentType;
59 wixComplexReferenceRow.ParentLanguage = parentLanguage;
60 wixComplexReferenceRow.Child = childId;
61 wixComplexReferenceRow.ChildType = childType;
62 wixComplexReferenceRow.IsPrimary = isPrimary;
63 56
64 this.CreateWixGroupRow(section, sourceLineNumbers, parentType, parentId, childType, childId); 57 var tuple = new WixComplexReferenceTuple(sourceLineNumbers)
58 {
59 Parent = parentId,
60 ParentType = parentType,
61 ParentLanguage = parentLanguage,
62 Child = childId,
63 ChildType = childType,
64 IsPrimary = isPrimary
65 };
66
67 section.Tuples.Add(tuple);
68
69 this.CreateWixGroupTuple(section, sourceLineNumbers, parentType, parentId, childType, childId);
65 } 70 }
66 71
72 [Obsolete]
67 public Identifier CreateDirectoryRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, Identifier id, string parentId, string name, ISet<string> sectionInlinedDirectoryIds, string shortName = null, string sourceName = null, string shortSourceName = null) 73 public Identifier CreateDirectoryRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, Identifier id, string parentId, string name, ISet<string> sectionInlinedDirectoryIds, string shortName = null, string sourceName = null, string shortSourceName = null)
68 { 74 {
75 return this.CreateDirectoryTuple(section, sourceLineNumbers, id, parentId, name, sectionInlinedDirectoryIds, shortName, sourceName, shortSourceName);
76 }
77
78 public Identifier CreateDirectoryTuple(IntermediateSection section, SourceLineNumber sourceLineNumbers, Identifier id, string parentId, string name, ISet<string> sectionInlinedDirectoryIds, string shortName = null, string sourceName = null, string shortSourceName = null)
79 {
69 string defaultDir; 80 string defaultDir;
70 81
71 if (name.Equals("SourceDir") || this.IsValidShortFilename(name, false)) 82 if (name.Equals("SourceDir") || this.IsValidShortFilename(name, false))
@@ -158,7 +169,7 @@ namespace WixToolset.Core.ExtensibilityServices
158 169
159 for (int i = pathStartsAt; i < inlineSyntax.Length; ++i) 170 for (int i = pathStartsAt; i < inlineSyntax.Length; ++i)
160 { 171 {
161 Identifier inlineId = this.CreateDirectoryRow(section, sourceLineNumbers, null, id, inlineSyntax[i], sectionInlinedDirectoryIds); 172 Identifier inlineId = this.CreateDirectoryTuple(section, sourceLineNumbers, null, id, inlineSyntax[i], sectionInlinedDirectoryIds);
162 id = inlineId.Id; 173 id = inlineId.Id;
163 } 174 }
164 } 175 }
@@ -175,17 +186,23 @@ namespace WixToolset.Core.ExtensibilityServices
175 public Identifier CreateIdentifier(string prefix, params string[] args) 186 public Identifier CreateIdentifier(string prefix, params string[] args)
176 { 187 {
177 var id = Common.GenerateIdentifier(prefix, args); 188 var id = Common.GenerateIdentifier(prefix, args);
178 return new Identifier(id, AccessModifier.Private); 189 return new Identifier(AccessModifier.Private, id);
179 } 190 }
180 191
181 public Identifier CreateIdentifierFromFilename(string filename) 192 public Identifier CreateIdentifierFromFilename(string filename)
182 { 193 {
183 var id = Common.GetIdentifierFromName(filename); 194 var id = Common.GetIdentifierFromName(filename);
184 return new Identifier(id, AccessModifier.Private); 195 return new Identifier(AccessModifier.Private, id);
185 } 196 }
186 197
198 [Obsolete]
187 public Identifier CreateRegistryRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, RegistryRootType root, string key, string name, string value, string componentId, bool escapeLeadingHash) 199 public Identifier CreateRegistryRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, RegistryRootType root, string key, string name, string value, string componentId, bool escapeLeadingHash)
188 { 200 {
201 return this.CreateRegistryTuple(section, sourceLineNumbers, root, key, name, value, componentId, escapeLeadingHash);
202 }
203
204 public Identifier CreateRegistryTuple(IntermediateSection section, SourceLineNumber sourceLineNumbers, RegistryRootType root, string key, string name, string value, string componentId, bool escapeLeadingHash)
205 {
189 if (RegistryRootType.Unknown == root) 206 if (RegistryRootType.Unknown == root)
190 { 207 {
191 throw new ArgumentOutOfRangeException(nameof(root)); 208 throw new ArgumentOutOfRangeException(nameof(root));
@@ -234,8 +251,14 @@ namespace WixToolset.Core.ExtensibilityServices
234 section.Tuples.Add(tuple); 251 section.Tuples.Add(tuple);
235 } 252 }
236 253
254 [Obsolete]
237 public void CreateWixGroupRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, ComplexReferenceParentType parentType, string parentId, ComplexReferenceChildType childType, string childId) 255 public void CreateWixGroupRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, ComplexReferenceParentType parentType, string parentId, ComplexReferenceChildType childType, string childId)
238 { 256 {
257 this.CreateWixGroupTuple(section, sourceLineNumbers, parentType, parentId, childType, childId);
258 }
259
260 public void CreateWixGroupTuple(IntermediateSection section, SourceLineNumber sourceLineNumbers, ComplexReferenceParentType parentType, string parentId, ComplexReferenceChildType childType, string childId)
261 {
239 if (null == parentId || ComplexReferenceParentType.Unknown == parentType) 262 if (null == parentId || ComplexReferenceParentType.Unknown == parentType)
240 { 263 {
241 return; 264 return;
@@ -257,8 +280,20 @@ namespace WixToolset.Core.ExtensibilityServices
257 section.Tuples.Add(tuple); 280 section.Tuples.Add(tuple);
258 } 281 }
259 282
283 [Obsolete]
260 public IntermediateTuple CreateRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, string tableName, Identifier identifier = null) 284 public IntermediateTuple CreateRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, string tableName, Identifier identifier = null)
261 { 285 {
286 return this.CreateTuple(section, sourceLineNumbers, tableName, identifier);
287 }
288
289 [Obsolete]
290 public IntermediateTuple CreateRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, TupleDefinitionType tupleType, Identifier identifier = null)
291 {
292 return this.CreateTuple(section, sourceLineNumbers, tupleType, identifier);
293 }
294
295 public IntermediateTuple CreateTuple(IntermediateSection section, SourceLineNumber sourceLineNumbers, string tableName, Identifier identifier = null)
296 {
262 if (this.Creator == null) 297 if (this.Creator == null)
263 { 298 {
264 this.CreateTupleDefinitionCreator(); 299 this.CreateTupleDefinitionCreator();
@@ -272,7 +307,7 @@ namespace WixToolset.Core.ExtensibilityServices
272 return CreateRow(section, sourceLineNumbers, tupleDefinition, identifier); 307 return CreateRow(section, sourceLineNumbers, tupleDefinition, identifier);
273 } 308 }
274 309
275 public IntermediateTuple CreateRow(IntermediateSection section, SourceLineNumber sourceLineNumbers, TupleDefinitionType tupleType, Identifier identifier = null) 310 public IntermediateTuple CreateTuple(IntermediateSection section, SourceLineNumber sourceLineNumbers, TupleDefinitionType tupleType, Identifier identifier = null)
276 { 311 {
277 var tupleDefinition = TupleDefinitions.ByType(tupleType); 312 var tupleDefinition = TupleDefinitions.ByType(tupleType);
278 313
@@ -331,7 +366,7 @@ namespace WixToolset.Core.ExtensibilityServices
331 366
332 public void EnsureTable(IntermediateSection section, SourceLineNumber sourceLineNumbers, string tableName) 367 public void EnsureTable(IntermediateSection section, SourceLineNumber sourceLineNumbers, string tableName)
333 { 368 {
334 var row = this.CreateRow(section, sourceLineNumbers, TupleDefinitionType.WixEnsureTable); 369 var row = this.CreateTuple(section, sourceLineNumbers, TupleDefinitionType.WixEnsureTable);
335 row.Set(0, tableName); 370 row.Set(0, tableName);
336 371
337 if (this.Creator == null) 372 if (this.Creator == null)
@@ -428,7 +463,7 @@ namespace WixToolset.Core.ExtensibilityServices
428 this.Messaging.Write(WarningMessages.IdentifierTooLong(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value)); 463 this.Messaging.Write(WarningMessages.IdentifierTooLong(sourceLineNumbers, attribute.Parent.Name.LocalName, attribute.Name.LocalName, value));
429 } 464 }
430 465
431 return new Identifier(value, access); 466 return new Identifier(access, value);
432 } 467 }
433 468
434 public string GetAttributeIdentifierValue(SourceLineNumber sourceLineNumbers, XAttribute attribute) 469 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
18 /// </summary> 18 /// </summary>
19 internal class WixGroupingOrdering 19 internal class WixGroupingOrdering
20 { 20 {
21 private IMessaging messageHandler; 21 private readonly IMessaging messageHandler;
22 private List<string> groupTypes; 22 private List<string> groupTypes;
23 private List<string> itemTypes; 23 private List<string> itemTypes;
24 private ItemCollection items; 24 private ItemCollection items;
25 private List<int> rowsUsed; 25 private readonly List<int> rowsUsed;
26 private bool loaded; 26 private bool loaded;
27 private bool encounteredError; 27 private bool encounteredError;
28 28
@@ -50,10 +50,10 @@ namespace WixToolset.Core.Link
50 /// </summary> 50 /// </summary>
51 /// <param name="groupTypes">Group types to include.</param> 51 /// <param name="groupTypes">Group types to include.</param>
52 /// <param name="itemTypes">Item types to include.</param> 52 /// <param name="itemTypes">Item types to include.</param>
53 public void UseTypes(IEnumerable<string> groupTypes, IEnumerable<string> itemTypes) 53 public void UseTypes(IEnumerable<ComplexReferenceParentType> groupTypes, IEnumerable<ComplexReferenceChildType> itemTypes)
54 { 54 {
55 this.groupTypes = new List<string>(groupTypes); 55 this.groupTypes = new List<string>(groupTypes.Select(g => g.ToString()));
56 this.itemTypes = new List<string>(itemTypes); 56 this.itemTypes = new List<string>(itemTypes.Select(i => i.ToString()));
57 57
58 this.items = new ItemCollection(); 58 this.items = new ItemCollection();
59 this.loaded = false; 59 this.loaded = false;
@@ -65,17 +65,18 @@ namespace WixToolset.Core.Link
65 /// <param name="parentType">The group type for the parent group to flatten.</param> 65 /// <param name="parentType">The group type for the parent group to flatten.</param>
66 /// <param name="parentId">The identifier of the parent group to flatten.</param> 66 /// <param name="parentId">The identifier of the parent group to flatten.</param>
67 /// <param name="removeUsedRows">Whether to remove used group rows before returning.</param> 67 /// <param name="removeUsedRows">Whether to remove used group rows before returning.</param>
68 public void FlattenAndRewriteRows(string parentType, string parentId, bool removeUsedRows) 68 public void FlattenAndRewriteRows(ComplexReferenceChildType parentType, string parentId, bool removeUsedRows)
69 { 69 {
70 Debug.Assert(this.groupTypes.Contains(parentType)); 70 var parentTypeString = parentType.ToString();
71 Debug.Assert(this.groupTypes.Contains(parentTypeString));
71 72
72 this.CreateOrderedList(parentType, parentId, out var orderedItems); 73 this.CreateOrderedList(parentTypeString, parentId, out var orderedItems);
73 if (this.encounteredError) 74 if (this.encounteredError)
74 { 75 {
75 return; 76 return;
76 } 77 }
77 78
78 this.CreateNewGroupRows(parentType, parentId, orderedItems); 79 this.CreateNewGroupRows(parentTypeString, parentId, orderedItems);
79 80
80 if (removeUsedRows) 81 if (removeUsedRows)
81 { 82 {
@@ -88,9 +89,10 @@ namespace WixToolset.Core.Link
88 /// </summary> 89 /// </summary>
89 /// <param name="parentType">The type of the parent group to flatten.</param> 90 /// <param name="parentType">The type of the parent group to flatten.</param>
90 /// <param name="removeUsedRows">Whether to remove used group rows before returning.</param> 91 /// <param name="removeUsedRows">Whether to remove used group rows before returning.</param>
91 public void FlattenAndRewriteGroups(string parentType, bool removeUsedRows) 92 public void FlattenAndRewriteGroups(ComplexReferenceParentType parentType, bool removeUsedRows)
92 { 93 {
93 Debug.Assert(this.groupTypes.Contains(parentType)); 94 var parentTypeString = parentType.ToString();
95 Debug.Assert(this.groupTypes.Contains(parentTypeString));
94 96
95 this.LoadFlattenOrderGroups(); 97 this.LoadFlattenOrderGroups();
96 if (this.encounteredError) 98 if (this.encounteredError)
@@ -100,10 +102,9 @@ namespace WixToolset.Core.Link
100 102
101 foreach (Item item in this.items) 103 foreach (Item item in this.items)
102 { 104 {
103 if (parentType == item.Type) 105 if (parentTypeString == item.Type)
104 { 106 {
105 List<Item> orderedItems; 107 this.CreateOrderedList(item.Type, item.Id, out var orderedItems);
106 this.CreateOrderedList(item.Type, item.Id, out orderedItems);
107 this.CreateNewGroupRows(item.Type, item.Id, orderedItems); 108 this.CreateNewGroupRows(item.Type, item.Id, orderedItems);
108 } 109 }
109 } 110 }
@@ -131,8 +132,7 @@ namespace WixToolset.Core.Link
131 return; 132 return;
132 } 133 }
133 134
134 Item parentItem; 135 if (!this.items.TryGetValue(parentType, parentId, out var parentItem))
135 if (!this.items.TryGetValue(parentType, parentId, out parentItem))
136 { 136 {
137 this.messageHandler.Write(ErrorMessages.IdentifierNotFound(parentType, parentId)); 137 this.messageHandler.Write(ErrorMessages.IdentifierNotFound(parentType, parentId));
138 return; 138 return;
@@ -360,9 +360,9 @@ namespace WixToolset.Core.Link
360 360
361 foreach (var row in this.EntrySection.Tuples.OfType<WixOrderingTuple>()) 361 foreach (var row in this.EntrySection.Tuples.OfType<WixOrderingTuple>())
362 { 362 {
363 var rowItemType = row.ItemType; 363 var rowItemType = row.ItemType.ToString();
364 var rowItemName = row.ItemId_; 364 var rowItemName = row.ItemId_;
365 var rowDependsOnType = row.DependsOnType; 365 var rowDependsOnType = row.DependsOnType.ToString();
366 var rowDependsOnName = row.DependsOnId_; 366 var rowDependsOnName = row.DependsOnId_;
367 367
368 // If this row specifies some other (unknown) type in either 368 // If this row specifies some other (unknown) type in either
@@ -510,8 +510,8 @@ namespace WixToolset.Core.Link
510 /// ordering dependencies.</remarks> 510 /// ordering dependencies.</remarks>
511 internal class Item 511 internal class Item
512 { 512 {
513 private ItemCollection afterItems; 513 private readonly ItemCollection afterItems;
514 private ItemCollection beforeItems; // for checking for circular references 514 private readonly ItemCollection beforeItems; // for checking for circular references
515 private bool flattenedAfterItems; 515 private bool flattenedAfterItems;
516 516
517 public Item(IntermediateTuple row, string type, string id) 517 public Item(IntermediateTuple row, string type, string id)
@@ -522,9 +522,9 @@ namespace WixToolset.Core.Link
522 522
523 this.Key = ItemCollection.CreateKeyFromTypeId(type, id); 523 this.Key = ItemCollection.CreateKeyFromTypeId(type, id);
524 524
525 afterItems = new ItemCollection(); 525 this.afterItems = new ItemCollection();
526 beforeItems = new ItemCollection(); 526 this.beforeItems = new ItemCollection();
527 flattenedAfterItems = false; 527 this.flattenedAfterItems = false;
528 } 528 }
529 529
530 public IntermediateTuple Row { get; private set; } 530 public IntermediateTuple Row { get; private set; }
@@ -540,8 +540,7 @@ namespace WixToolset.Core.Link
540 } 540 }
541#endif // DEBUG 541#endif // DEBUG
542 542
543 private ItemCollection childItems = new ItemCollection(); 543 public ItemCollection ChildItems { get; } = new ItemCollection();
544 public ItemCollection ChildItems { get { return childItems; } }
545 544
546 /// <summary> 545 /// <summary>
547 /// Removes any nested groups under this item and replaces 546 /// Removes any nested groups under this item and replaces
@@ -614,7 +613,7 @@ namespace WixToolset.Core.Link
614 { 613 {
615 if (this.ShouldItemPropagateChildOrdering()) 614 if (this.ShouldItemPropagateChildOrdering())
616 { 615 {
617 foreach (Item childItem in this.childItems) 616 foreach (Item childItem in this.ChildItems)
618 { 617 {
619 childItem.AddAfter(this.afterItems, messageHandler); 618 childItem.AddAfter(this.afterItems, messageHandler);
620 } 619 }
@@ -667,9 +666,9 @@ namespace WixToolset.Core.Link
667 // first payload to be the entrypoint. 666 // first payload to be the entrypoint.
668 private bool ShouldItemPropagateChildOrdering() 667 private bool ShouldItemPropagateChildOrdering()
669 { 668 {
670 if (String.Equals("Package", this.Type, StringComparison.Ordinal) || 669 if (String.Equals(nameof(ComplexReferenceChildType.Package), this.Type, StringComparison.Ordinal) ||
671 (String.Equals("Container", this.Type, StringComparison.Ordinal) && 670 (String.Equals(nameof(ComplexReferenceParentType.Container), this.Type, StringComparison.Ordinal) &&
672 !String.Equals(Compiler.BurnUXContainerId, this.Id, StringComparison.Ordinal))) 671 !String.Equals(Compiler.BurnUXContainerId.Id, this.Id, StringComparison.Ordinal)))
673 { 672 {
674 return false; 673 return false;
675 } 674 }
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
20 /// </summary> 20 /// </summary>
21 internal class Linker : ILinker 21 internal class Linker : ILinker
22 { 22 {
23 private static readonly char[] colonCharacter = ":".ToCharArray(); 23 private static readonly char[] ColonCharacter = new[] { ':' };
24 private static readonly string emptyGuid = Guid.Empty.ToString("B"); 24 private static readonly string EmptyGuid = Guid.Empty.ToString("B");
25 25
26 private readonly bool sectionIdOnRows; 26 private readonly bool sectionIdOnRows;
27 27
@@ -428,21 +428,22 @@ namespace WixToolset.Core
428 // check for colliding values and collect the wix variable rows 428 // check for colliding values and collect the wix variable rows
429 { 429 {
430 var row = (WixVariableTuple)tuple; 430 var row = (WixVariableTuple)tuple;
431 var id = row.Id.Id;
431 432
432 if (wixVariables.TryGetValue(row.WixVariable, out var collidingRow)) 433 if (wixVariables.TryGetValue(id, out var collidingRow))
433 { 434 {
434 if (collidingRow.Overridable && !row.Overridable) 435 if (collidingRow.Overridable && !row.Overridable)
435 { 436 {
436 wixVariables[row.WixVariable] = row; 437 wixVariables[id] = row;
437 } 438 }
438 else if (!row.Overridable || (collidingRow.Overridable && row.Overridable)) 439 else if (!row.Overridable || (collidingRow.Overridable && row.Overridable))
439 { 440 {
440 this.OnMessage(ErrorMessages.WixVariableCollision(row.SourceLineNumbers, row.WixVariable)); 441 this.OnMessage(ErrorMessages.WixVariableCollision(row.SourceLineNumbers, id));
441 } 442 }
442 } 443 }
443 else 444 else
444 { 445 {
445 wixVariables.Add(row.WixVariable, row); 446 wixVariables.Add(id, row);
446 } 447 }
447 } 448 }
448 449
@@ -1609,14 +1610,14 @@ namespace WixToolset.Core
1609 var groups = new WixGroupingOrdering(entrySection, this.Messaging); 1610 var groups = new WixGroupingOrdering(entrySection, this.Messaging);
1610 1611
1611 // Create UX payloads and Package payloads 1612 // Create UX payloads and Package payloads
1612 groups.UseTypes(new string[] { "Container", "Layout", "PackageGroup", "PayloadGroup", "Package" }, new string[] { "PackageGroup", "Package", "PayloadGroup", "Payload" }); 1613 groups.UseTypes(new[] { ComplexReferenceParentType.Container, ComplexReferenceParentType.Layout, ComplexReferenceParentType.PackageGroup, ComplexReferenceParentType.PayloadGroup, ComplexReferenceParentType.Package }, new[] { ComplexReferenceChildType.PackageGroup, ComplexReferenceChildType.Package, ComplexReferenceChildType.PayloadGroup, ComplexReferenceChildType.Payload });
1613 groups.FlattenAndRewriteGroups("Package", false); 1614 groups.FlattenAndRewriteGroups(ComplexReferenceParentType.Package, false);
1614 groups.FlattenAndRewriteGroups("Container", false); 1615 groups.FlattenAndRewriteGroups(ComplexReferenceParentType.Container, false);
1615 groups.FlattenAndRewriteGroups("Layout", false); 1616 groups.FlattenAndRewriteGroups(ComplexReferenceParentType.Layout, false);
1616 1617
1617 // Create Chain packages... 1618 // Create Chain packages...
1618 groups.UseTypes(new string[] { "PackageGroup" }, new string[] { "Package", "PackageGroup" }); 1619 groups.UseTypes(new[] { ComplexReferenceParentType.PackageGroup }, new[] { ComplexReferenceChildType.Package, ComplexReferenceChildType.PackageGroup });
1619 groups.FlattenAndRewriteRows("PackageGroup", "WixChain", false); 1620 groups.FlattenAndRewriteRows(ComplexReferenceChildType.PackageGroup, "WixChain", false);
1620 1621
1621 groups.RemoveUsedGroupRows(); 1622 groups.RemoveUsedGroupRows();
1622 } 1623 }
@@ -1702,7 +1703,7 @@ namespace WixToolset.Core
1702 var connectionId = row.AsString(connectionColumn); 1703 var connectionId = row.AsString(connectionColumn);
1703 var featureId = row.AsString(featureColumn); 1704 var featureId = row.AsString(featureColumn);
1704 1705
1705 if (emptyGuid == featureId) 1706 if (EmptyGuid == featureId)
1706 { 1707 {
1707 var connection = connectToFeatures[connectionId]; 1708 var connection = connectToFeatures[connectionId];
1708 1709
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
66 /// <summary> 66 /// <summary>
67 /// Event for resolved variables. 67 /// Event for resolved variables.
68 /// </summary> 68 /// </summary>
69 public event ResolvedVariableEventHandler ResolvedVariable; 69 /// TOOD: Remove?
70 //public event ResolvedVariableEventHandler ResolvedVariable;
70 71
71 /// <summary> 72 /// <summary>
72 /// Get the source line information for the current element. The precompiler will insert 73 /// 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
213 var wixVariableTuples = context.IntermediateRepresentation.Sections.SelectMany(s => s.Tuples).OfType<WixVariableTuple>(); 213 var wixVariableTuples = context.IntermediateRepresentation.Sections.SelectMany(s => s.Tuples).OfType<WixVariableTuple>();
214 foreach (var tuple in wixVariableTuples) 214 foreach (var tuple in wixVariableTuples)
215 { 215 {
216 context.VariableResolver.AddVariable(tuple.SourceLineNumbers, tuple.WixVariable, tuple.Value, tuple.Overridable); 216 context.VariableResolver.AddVariable(tuple.SourceLineNumbers, tuple.Id.Id, tuple.Value, tuple.Overridable);
217 } 217 }
218 } 218 }
219 219
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 @@
1// 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.
2
3namespace WixToolset.Core
4{
5 using System;
6 using System.Diagnostics.CodeAnalysis;
7
8 /// <summary>
9 /// Summary information values for the CharCount property in transforms.
10 /// </summary>
11 [Flags]
12 [SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")]
13 public enum TransformFlags
14 {
15 /// <summary>Ignore error when adding a row that exists.</summary>
16 ErrorAddExistingRow = 0x1,
17
18 /// <summary>Ignore error when deleting a row that does not exist.</summary>
19 ErrorDeleteMissingRow = 0x2,
20
21 /// <summary>Ignore error when adding a table that exists. </summary>
22 ErrorAddExistingTable = 0x4,
23
24 /// <summary>Ignore error when deleting a table that does not exist. </summary>
25 ErrorDeleteMissingTable = 0x8,
26
27 /// <summary>Ignore error when updating a row that does not exist. </summary>
28 ErrorUpdateMissingRow = 0x10,
29
30 /// <summary>Ignore error when transform and database code pages do not match, and their code pages are neutral.</summary>
31 ErrorChangeCodePage = 0x20,
32
33 /// <summary>Default language must match base database. </summary>
34 ValidateLanguage = 0x10000,
35
36 /// <summary>Product must match base database.</summary>
37 ValidateProduct = 0x20000,
38
39 /// <summary>Check major version only. </summary>
40 ValidateMajorVersion = 0x80000,
41
42 /// <summary>Check major and minor versions only. </summary>
43 ValidateMinorVersion = 0x100000,
44
45 /// <summary>Check major, minor, and update versions.</summary>
46 ValidateUpdateVersion = 0x200000,
47
48 /// <summary>Installed version lt base version. </summary>
49 ValidateNewLessBaseVersion = 0x400000,
50
51 /// <summary>Installed version lte base version. </summary>
52 ValidateNewLessEqualBaseVersion = 0x800000,
53
54 /// <summary>Installed version eq base version. </summary>
55 ValidateNewEqualBaseVersion = 0x1000000,
56
57 /// <summary>Installed version gte base version.</summary>
58 ValidateNewGreaterEqualBaseVersion = 0x2000000,
59
60 /// <summary>Installed version gt base version.</summary>
61 ValidateNewGreaterBaseVersion = 0x4000000,
62
63 /// <summary>UpgradeCode must match base database.</summary>
64 ValidateUpgradeCode = 0x8000000,
65
66 /// <summary>Masks all version checks on ProductVersion.</summary>
67 ProductVersionMask = ValidateMajorVersion | ValidateMinorVersion | ValidateUpdateVersion,
68
69 /// <summary>Masks all operations on ProductVersion.</summary>
70 ProductVersionOperatorMask = ValidateNewLessBaseVersion | ValidateNewLessEqualBaseVersion | ValidateNewEqualBaseVersion | ValidateNewGreaterEqualBaseVersion | ValidateNewGreaterBaseVersion,
71
72 /// <summary>Default value for instance transforms.</summary>
73 InstanceTransformDefault = ErrorAddExistingRow | ErrorDeleteMissingRow | ErrorAddExistingTable | ErrorDeleteMissingTable | ErrorUpdateMissingRow | ErrorChangeCodePage | ValidateProduct | ValidateUpdateVersion | ValidateNewGreaterEqualBaseVersion,
74
75 /// <summary>Default value for language transforms.</summary>
76 LanguageTransformDefault = ErrorAddExistingRow | ErrorDeleteMissingRow | ErrorAddExistingTable | ErrorDeleteMissingTable | ErrorUpdateMissingRow | ErrorChangeCodePage | ValidateProduct,
77
78 /// <summary>Default value for patch transforms.</summary>
79 PatchTransformDefault = ErrorAddExistingRow | ErrorDeleteMissingRow | ErrorAddExistingTable | ErrorDeleteMissingTable | ErrorUpdateMissingRow | ValidateProduct | ValidateUpdateVersion | ValidateNewEqualBaseVersion | ValidateUpgradeCode,
80 }
81}