diff options
Diffstat (limited to '')
-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 | } | ||