diff options
Diffstat (limited to 'src/WixToolset.Core/Compiler_PatchCreation.cs')
| -rw-r--r-- | src/WixToolset.Core/Compiler_PatchCreation.cs | 1313 |
1 files changed, 1313 insertions, 0 deletions
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 | |||
| 3 | namespace 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 | } | ||
