main
cs 2,618 lines 120 KB
Raw
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.Iis
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.Extensibility;
11 using WixToolset.Extensibility.Data;
12 using WixToolset.Iis.Symbols;
13
14 /// <summary>
15 /// The compiler for the WiX Toolset Internet Information Services Extension.
16 /// </summary>
17 public sealed class IIsCompiler : BaseCompilerExtension
18 {
19 public override XNamespace Namespace => "http://wixtoolset.org/schemas/v4/wxs/iis";
20
21 /// <summary>
22 /// Types of objects that custom HTTP Headers can be applied to.
23 /// </summary>
24 /// <remarks>Note that this must be kept in sync with the eHttpHeaderParentType in scahttpheader.h.</remarks>
25 private enum HttpHeaderParentType
26 {
27 /// <summary>Custom HTTP Header is to be applied to a Web Virtual Directory.</summary>
28 WebVirtualDir = 1,
29 /// <summary>Custom HTTP Header is to be applied to a Web Site.</summary>
30 WebSite = 2,
31 }
32
33 /// <summary>
34 /// Types of objects that MimeMaps can be applied to.
35 /// </summary>
36 /// <remarks>Note that this must be kept in sync with the eMimeMapParentType in scamimemap.h.</remarks>
37 private enum MimeMapParentType
38 {
39 /// <summary>MimeMap is to be applied to a Web Virtual Directory.</summary>
40 WebVirtualDir = 1,
41 WebSite = 2,
42 }
43
44 /// <summary>
45 /// Types of objects that custom WebErrors can be applied to.
46 /// </summary>
47 /// <remarks>Note that this must be kept in sync with the eWebErrorParentType in scaweberror.h.</remarks>
48 private enum WebErrorParentType
49 {
50 /// <summary>Custom WebError is to be applied to a Web Virtual Directory.</summary>
51 WebVirtualDir = 1,
52
53 /// <summary>Custom WebError is to be applied to a Web Site.</summary>
54 WebSite = 2,
55 }
56
57 /// <summary>
58 /// Processes an element for the Compiler.
59 /// </summary>
60 /// <param name="sourceLineNumbers">Source line number for the parent element.</param>
61 /// <param name="parentElement">Parent element of element to process.</param>
62 /// <param name="element">Element to process.</param>
63 /// <param name="contextValues">Extra information about the context in which this element is being parsed.</param>
64 public override void ParseElement(Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, IDictionary<string, string> context)
65 {
66 switch (parentElement.Name.LocalName)
67 {
68 case "Component":
69 var componentId = context["ComponentId"];
70
71 switch (element.Name.LocalName)
72 {
73 case "Certificate":
74 this.ParseCertificateElement(intermediate, section, element, componentId);
75 break;
76 case "WebAppPool":
77 this.ParseWebAppPoolElement(intermediate, section, element, componentId);
78 break;
79 case "WebDir":
80 this.ParseWebDirElement(intermediate, section, element, componentId, null);
81 break;
82 case "WebFilter":
83 this.ParseWebFilterElement(intermediate, section, element, componentId, null);
84 break;
85 case "WebProperty":
86 this.ParseWebPropertyElement(intermediate, section, element, componentId);
87 break;
88 case "WebServiceExtension":
89 this.ParseWebServiceExtensionElement(intermediate, section, element, componentId);
90 break;
91 case "WebSite":
92 this.ParseWebSiteElement(intermediate, section, element, componentId);
93 break;
94 case "WebVirtualDir":
95 this.ParseWebVirtualDirElement(intermediate, section, element, componentId, null, null);
96 break;
97 default:
98 this.ParseHelper.UnexpectedElement(parentElement, element);
99 break;
100 }
101 break;
102 case "Fragment":
103 case "Module":
104 case "Package":
105 switch (element.Name.LocalName)
106 {
107 case "WebApplication":
108 this.ParseWebApplicationElement(intermediate, section, element);
109 break;
110 case "WebAppPool":
111 this.ParseWebAppPoolElement(intermediate, section, element, null);
112 break;
113 case "WebDirProperties":
114 this.ParseWebDirPropertiesElement(intermediate, section, element, null);
115 break;
116 case "WebLog":
117 this.ParseWebLogElement(intermediate, section, element);
118 break;
119 case "WebSite":
120 this.ParseWebSiteElement(intermediate, section, element, null);
121 break;
122 default:
123 this.ParseHelper.UnexpectedElement(parentElement, element);
124 break;
125 }
126 break;
127 default:
128 this.ParseHelper.UnexpectedElement(parentElement, element);
129 break;
130 }
131 }
132
133 /// <summary>
134 /// Parses a certificate element.
135 /// </summary>
136 /// <param name="element">Element to parse.</param>
137 /// <param name="componentId">Identifier for parent component.</param>
138 private void ParseCertificateElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
139 {
140 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
141 Identifier id = null;
142 int attributes = 8; // SCA_CERT_ATTRIBUTE_VITAL
143 string binaryRef = null;
144 string certificatePath = null;
145 string name = null;
146 string pfxPassword = null;
147 int storeLocation = 0;
148 string storeName = null;
149
150 foreach (var attrib in element.Attributes())
151 {
152 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
153 {
154 switch (attrib.Name.LocalName)
155 {
156 case "Id":
157 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
158 break;
159 case "BinaryRef":
160 attributes |= 2; // SCA_CERT_ATTRIBUTE_BINARYDATA
161 binaryRef = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
162 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.Binary, binaryRef);
163 break;
164 case "CertificatePath":
165 certificatePath = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
166 break;
167 case "Name":
168 name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
169 break;
170 case "Overwrite":
171 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
172 {
173 attributes |= 4; // SCA_CERT_ATTRIBUTE_OVERWRITE
174 }
175 else
176 {
177 attributes &= ~4; // SCA_CERT_ATTRIBUTE_OVERWRITE
178 }
179 break;
180 case "PFXPassword":
181 pfxPassword = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
182 break;
183 case "Request":
184 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
185 {
186 attributes |= 1; // SCA_CERT_ATTRIBUTE_REQUEST
187 }
188 else
189 {
190 attributes &= ~1; // SCA_CERT_ATTRIBUTE_REQUEST
191 }
192 break;
193 case "StoreLocation":
194 var storeLocationValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
195 if (0 < storeLocationValue.Length)
196 {
197 switch (storeLocationValue)
198 {
199 case "currentUser":
200 storeLocation = 1; // SCA_CERTSYSTEMSTORE_CURRENTUSER
201 break;
202 case "localMachine":
203 storeLocation = 2; // SCA_CERTSYSTEMSTORE_LOCALMACHINE
204 break;
205 default:
206 storeLocation = -1;
207 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "StoreLocation", storeLocationValue, "currentUser", "localMachine"));
208 break;
209 }
210 }
211 break;
212 case "StoreName":
213 var storeNameValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
214 if (0 < storeNameValue.Length)
215 {
216 switch (storeNameValue)
217 {
218 case "ca":
219 storeName = "CA";
220 break;
221 case "my":
222 case "personal":
223 storeName = "MY";
224 break;
225 case "request":
226 storeName = "REQUEST";
227 break;
228 case "root":
229 storeName = "Root";
230 break;
231 case "otherPeople":
232 storeName = "AddressBook";
233 break;
234 case "trustedPeople":
235 storeName = "TrustedPeople";
236 break;
237 case "trustedPublisher":
238 storeName = "TrustedPublisher";
239 break;
240 default:
241 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "StoreName", storeNameValue, "ca", "my", "request", "root", "otherPeople", "trustedPeople", "trustedPublisher"));
242 break;
243 }
244 }
245 break;
246 case "Vital":
247 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
248 {
249 attributes |= 8; // SCA_CERT_ATTRIBUTE_VITAL
250 }
251 else
252 {
253 attributes &= ~8; // SCA_CERT_ATTRIBUTE_VITAL
254 }
255 break;
256 default:
257 this.ParseHelper.UnexpectedAttribute(element, attrib);
258 break;
259 }
260 }
261 else
262 {
263 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
264 }
265 }
266
267 if (null == id)
268 {
269 id = this.ParseHelper.CreateIdentifier("crt", componentId, binaryRef, certificatePath);
270 }
271
272 if (null == name)
273 {
274 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
275 }
276
277 if (0 == storeLocation)
278 {
279 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "StoreLocation"));
280 }
281
282 if (null == storeName)
283 {
284 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "StoreName"));
285 }
286
287 if (null != binaryRef && null != certificatePath)
288 {
289 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "BinaryRef", "CertificatePath", certificatePath));
290 }
291 else if (null == binaryRef && null == certificatePath)
292 {
293 this.Messaging.Write(ErrorMessages.ExpectedAttributes(sourceLineNumbers, element.Name.LocalName, "BinaryRef", "CertificatePath"));
294 }
295
296 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
297
298 // Reference InstallCertificates and UninstallCertificates since nothing will happen without them
299 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4InstallCertificates", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
300 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4UninstallCertificates", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
301 this.ParseHelper.EnsureTable(section, sourceLineNumbers, IisTableDefinitions.CertificateHash); // Certificate CustomActions require the CertificateHash table
302
303 if (!this.Messaging.EncounteredError)
304 {
305 section.AddSymbol(new CertificateSymbol(sourceLineNumbers, id)
306 {
307 ComponentRef = componentId,
308 Name = name,
309 StoreLocation = storeLocation,
310 StoreName = storeName,
311 Attributes = attributes,
312 BinaryRef = binaryRef,
313 CertificatePath = certificatePath,
314 PFXPassword = pfxPassword,
315 });
316 }
317 }
318
319 /// <summary>
320 /// Parses a CertificateRef extension element.
321 /// </summary>
322 /// <param name="element">Element to parse.</param>
323 /// <param name="webId">Identifier for parent web site.</param>
324 private void ParseCertificateRefElement(Intermediate intermediate, IntermediateSection section, XElement element, string webId)
325 {
326 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
327 Identifier id = null;
328
329 foreach (var attrib in element.Attributes())
330 {
331 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
332 {
333 switch (attrib.Name.LocalName)
334 {
335 case "Id":
336 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
337 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.Certificate, id.Id);
338 break;
339 default:
340 this.ParseHelper.UnexpectedAttribute(element, attrib);
341 break;
342 }
343 }
344 else
345 {
346 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
347 }
348 }
349
350 if (null == id)
351 {
352 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Id"));
353 }
354
355 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
356
357 if (!this.Messaging.EncounteredError)
358 {
359 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.Certificate, id.Id);
360
361 section.AddSymbol(new IIsWebSiteCertificatesSymbol(sourceLineNumbers)
362 {
363 WebRef = webId,
364 CertificateRef = id.Id,
365 });
366 }
367 }
368
369 /// <summary>
370 /// Parses a mime map element.
371 /// </summary>
372 /// <param name="element">Element to parse.</param>
373 /// <param name="parentId">Identifier for parent symbol.</param>
374 /// <param name="parentType">Type that parentId refers to.</param>
375 private void ParseMimeMapElement(Intermediate intermediate, IntermediateSection section, XElement element, string parentId, MimeMapParentType parentType)
376 {
377 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
378 Identifier id = null;
379 string extension = null;
380 string type = null;
381
382 foreach (var attrib in element.Attributes())
383 {
384 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
385 {
386 switch (attrib.Name.LocalName)
387 {
388 case "Id":
389 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
390 break;
391 case "Extension":
392 extension = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
393 break;
394 case "Type":
395 type = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
396 break;
397 default:
398 this.ParseHelper.UnexpectedAttribute(element, attrib);
399 break;
400 }
401 }
402 else
403 {
404 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
405 }
406 }
407
408 if (null == id)
409 {
410 id = this.ParseHelper.CreateIdentifier("imm", parentId, type, extension);
411 }
412
413 if (null == extension)
414 {
415 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Extension"));
416 }
417 else if (0 < extension.Length)
418 {
419 if (!extension.StartsWith(".", StringComparison.Ordinal))
420 {
421 this.Messaging.Write(IIsErrors.MimeMapExtensionMissingPeriod(sourceLineNumbers, element.Name.LocalName, "Extension", extension));
422 }
423 }
424
425 if (null == type)
426 {
427 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Type"));
428 }
429
430 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
431
432 if (!this.Messaging.EncounteredError)
433 {
434 section.AddSymbol(new IIsMimeMapSymbol(sourceLineNumbers, id)
435 {
436 ParentType = (int)parentType,
437 ParentValue = parentId,
438 MimeType = type,
439 Extension = extension,
440 });
441 }
442 }
443
444 /// <summary>
445 /// Parses a recycle time element.
446 /// </summary>
447 /// <param name="element">Element to parse.</param>
448 /// <returns>Recycle time value.</returns>
449 private string ParseRecycleTimeElement(Intermediate intermediate, IntermediateSection section, XElement element)
450 {
451 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
452 string value = null;
453
454 foreach (var attrib in element.Attributes())
455 {
456 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
457 {
458 switch (attrib.Name.LocalName)
459 {
460 case "Value":
461 value = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
462 break;
463 default:
464 this.ParseHelper.UnexpectedAttribute(element, attrib);
465 break;
466 }
467 }
468 else
469 {
470 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
471 }
472 }
473
474 if (null == value)
475 {
476 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Value"));
477 }
478
479 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
480
481 return value;
482 }
483
484 /// <summary>
485 /// Parses a web address element.
486 /// </summary>
487 /// <param name="element">Element to parse.</param>
488 /// <param name="parentWeb">Identifier of parent web site.</param>
489 /// <returns>Identifier for web address.</returns>
490 private string ParseWebAddressElement(Intermediate intermediate, IntermediateSection section, XElement element, string parentWeb)
491 {
492 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
493 Identifier id = null;
494 string header = null;
495 string ip = null;
496 string port = null;
497 var secure = false;
498
499 foreach (var attrib in element.Attributes())
500 {
501 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
502 {
503 switch (attrib.Name.LocalName)
504 {
505 case "Id":
506 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
507 break;
508 case "Header":
509 header = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
510 break;
511 case "IP":
512 ip = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
513 break;
514 case "Port":
515 port = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
516 break;
517 case "Secure":
518 secure = YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
519 break;
520 default:
521 this.ParseHelper.UnexpectedAttribute(element, attrib);
522 break;
523 }
524 }
525 else
526 {
527 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
528 }
529 }
530
531 if (null == id)
532 {
533 id = this.ParseHelper.CreateIdentifier("iwa", parentWeb, ip, port);
534 }
535
536 if (null == port)
537 {
538 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Port"));
539 }
540
541 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
542
543 if (!this.Messaging.EncounteredError)
544 {
545 section.AddSymbol(new IIsWebAddressSymbol(sourceLineNumbers, id)
546 {
547 WebRef = parentWeb,
548 IP = ip,
549 Port = port,
550 Header = header,
551 Secure = secure ? 1 : 0,
552 });
553 }
554
555 return id?.Id;
556 }
557
558 /// <summary>
559 /// Parses a web application element.
560 /// </summary>
561 /// <param name="element">Element to parse.</param>
562 /// <returns>Identifier for web application.</returns>
563 private string ParseWebApplicationElement(Intermediate intermediate, IntermediateSection section, XElement element)
564 {
565 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
566 Identifier id = null;
567 var allowSessions = YesNoDefaultType.Default;
568 string appPool = null;
569 var buffer = YesNoDefaultType.Default;
570 var clientDebugging = YesNoDefaultType.Default;
571 string defaultScript = null;
572 int isolation = 0;
573 string name = null;
574 var parentPaths = YesNoDefaultType.Default;
575 var scriptTimeout = CompilerConstants.IntegerNotSet;
576 var sessionTimeout = CompilerConstants.IntegerNotSet;
577 var serverDebugging = YesNoDefaultType.Default;
578
579 foreach (var attrib in element.Attributes())
580 {
581 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
582 {
583 switch (attrib.Name.LocalName)
584 {
585 case "Id":
586 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
587 break;
588 case "AllowSessions":
589 allowSessions = this.ParseHelper.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib);
590 break;
591 case "Buffer":
592 buffer = this.ParseHelper.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib);
593 break;
594 case "ClientDebugging":
595 clientDebugging = this.ParseHelper.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib);
596 break;
597 case "DefaultScript":
598 defaultScript = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
599 if (0 < defaultScript.Length)
600 {
601 switch (defaultScript)
602 {
603 case "JScript":
604 case "VBScript":
605 // these are valid values
606 break;
607 default:
608 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, defaultScript, "JScript", "VBScript"));
609 break;
610 }
611 }
612 break;
613 case "Isolation":
614 string isolationValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
615 if (0 < isolationValue.Length)
616 {
617 switch (isolationValue)
618 {
619 case "low":
620 isolation = 0;
621 break;
622 case "medium":
623 isolation = 2;
624 break;
625 case "high":
626 isolation = 1;
627 break;
628 default:
629 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, isolationValue, "low", "medium", "high"));
630 break;
631 }
632 }
633 break;
634 case "Name":
635 name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
636 break;
637 case "ParentPaths":
638 parentPaths = this.ParseHelper.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib);
639 break;
640 case "ScriptTimeout":
641 scriptTimeout = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
642 break;
643 case "ServerDebugging":
644 serverDebugging = this.ParseHelper.GetAttributeYesNoDefaultValue(sourceLineNumbers, attrib);
645 break;
646 case "SessionTimeout":
647 sessionTimeout = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
648 break;
649 case "WebAppPool":
650 appPool = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
651 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsAppPool, appPool);
652 break;
653 default:
654 this.ParseHelper.UnexpectedAttribute(element, attrib);
655 break;
656 }
657 }
658 else
659 {
660 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
661 }
662 }
663
664 if (null == id)
665 {
666 id = this.ParseHelper.CreateIdentifier("wap", name, appPool);
667 }
668
669 if (null == name)
670 {
671 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
672 }
673 else if (-1 != name.IndexOf("\\", StringComparison.Ordinal))
674 {
675 this.Messaging.Write(IIsErrors.IllegalCharacterInAttributeValue(sourceLineNumbers, element.Name.LocalName, "Name", name, '\\'));
676 }
677
678 foreach (var child in element.Elements())
679 {
680 if (this.Namespace == child.Name.Namespace)
681 {
682 switch (child.Name.LocalName)
683 {
684 case "WebApplicationExtension":
685 this.ParseWebApplicationExtensionElement(intermediate, section, child, id?.Id);
686 break;
687 default:
688 this.ParseHelper.UnexpectedElement(element, child);
689 break;
690 }
691 }
692 else
693 {
694 this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child);
695 }
696 }
697
698 if (!this.Messaging.EncounteredError)
699 {
700 var symbol = section.AddSymbol(new IIsWebApplicationSymbol(sourceLineNumbers, id)
701 {
702 Name = name,
703 Isolation = isolation,
704 DefaultScript = defaultScript,
705 AppPoolRef = appPool,
706 });
707
708 if (YesNoDefaultType.Default != allowSessions)
709 {
710 symbol.AllowSessions = YesNoDefaultType.Yes == allowSessions ? 1 : 0;
711 }
712
713 if (CompilerConstants.IntegerNotSet != sessionTimeout)
714 {
715 symbol.SessionTimeout = sessionTimeout;
716 }
717
718 if (YesNoDefaultType.Default != buffer)
719 {
720 symbol.Buffer = YesNoDefaultType.Yes == buffer ? 1 : 0;
721 }
722
723 if (YesNoDefaultType.Default != parentPaths)
724 {
725 symbol.ParentPaths = YesNoDefaultType.Yes == parentPaths ? 1 : 0;
726 }
727
728 if (CompilerConstants.IntegerNotSet != scriptTimeout)
729 {
730 symbol.ScriptTimeout = scriptTimeout;
731 }
732
733 if (YesNoDefaultType.Default != serverDebugging)
734 {
735 symbol.ServerDebugging = YesNoDefaultType.Yes == serverDebugging ? 1 : 0;
736 }
737
738 if (YesNoDefaultType.Default != clientDebugging)
739 {
740 symbol.ClientDebugging = YesNoDefaultType.Yes == clientDebugging ? 1 : 0;
741 }
742 }
743
744 return id?.Id;
745 }
746
747 /// <summary>
748 /// Parses a web application extension element.
749 /// </summary>
750 /// <param name="element">Element to parse.</param>
751 /// <param name="application">Identifier for parent web application.</param>
752 private void ParseWebApplicationExtensionElement(Intermediate intermediate, IntermediateSection section, XElement element, string application)
753 {
754 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
755 int attributes = 0;
756 string executable = null;
757 string extension = null;
758 string verbs = null;
759
760 foreach (var attrib in element.Attributes())
761 {
762 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
763 {
764 switch (attrib.Name.LocalName)
765 {
766 case "CheckPath":
767 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
768 {
769 attributes |= 4;
770 }
771 else
772 {
773 attributes &= ~4;
774 }
775 break;
776 case "Executable":
777 executable = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
778 break;
779 case "Extension":
780 extension = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
781 break;
782 case "Script":
783 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
784 {
785 attributes |= 1;
786 }
787 else
788 {
789 attributes &= ~1;
790 }
791 break;
792 case "Verbs":
793 verbs = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
794 break;
795 default:
796 this.ParseHelper.UnexpectedAttribute(element, attrib);
797 break;
798 }
799 }
800 else
801 {
802 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
803 }
804 }
805
806 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
807
808 if (!this.Messaging.EncounteredError)
809 {
810 var symbol = section.AddSymbol(new IIsWebApplicationExtensionSymbol(sourceLineNumbers)
811 {
812 ApplicationRef = application,
813 Extension = extension,
814 Verbs = verbs,
815 Executable = executable,
816 });
817
818 if (0 < attributes)
819 {
820 symbol.Attributes = attributes;
821 }
822 }
823 }
824
825 /// <summary>
826 /// Parses web application pool element.
827 /// </summary>
828 /// <param name="element">Element to parse.</param>
829 /// <param name="componentId">Optional identifier of parent component.</param>
830 private void ParseWebAppPoolElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
831 {
832 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
833 Identifier id = null;
834 int attributes = 0;
835 var cpuAction = CompilerConstants.IntegerNotSet;
836 string cpuMon = null;
837 var idleTimeout = CompilerConstants.IntegerNotSet;
838 int maxCpuUsage = 0;
839 var maxWorkerProcs = CompilerConstants.IntegerNotSet;
840 string managedRuntimeVersion = null;
841 string managedPipelineMode = null;
842 string name = null;
843 var privateMemory = CompilerConstants.IntegerNotSet;
844 var queueLimit = CompilerConstants.IntegerNotSet;
845 var recycleMinutes = CompilerConstants.IntegerNotSet;
846 var recycleRequests = CompilerConstants.IntegerNotSet;
847 string recycleTimes = null;
848 var refreshCpu = CompilerConstants.IntegerNotSet;
849 string user = null;
850 var virtualMemory = CompilerConstants.IntegerNotSet;
851
852 foreach (var attrib in element.Attributes())
853 {
854 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
855 {
856 switch (attrib.Name.LocalName)
857 {
858 case "Id":
859 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
860 break;
861 case "CpuAction":
862 if (null == componentId)
863 {
864 this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
865 }
866
867 var cpuActionValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
868 if (0 < cpuActionValue.Length)
869 {
870 switch (cpuActionValue)
871 {
872 case "shutdown":
873 cpuAction = 1;
874 break;
875 case "none":
876 cpuAction = 0;
877 break;
878 default:
879 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, cpuActionValue, "shutdown", "none"));
880 break;
881 }
882 }
883 break;
884 case "Identity":
885 if (null == componentId)
886 {
887 this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
888 }
889
890 var identityValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
891 if (0 < identityValue.Length)
892 {
893 switch (identityValue)
894 {
895 case "networkService":
896 attributes |= 1;
897 break;
898 case "localService":
899 attributes |= 2;
900 break;
901 case "localSystem":
902 attributes |= 4;
903 break;
904 case "other":
905 attributes |= 8;
906 break;
907 case "applicationPoolIdentity":
908 attributes |= 0x10;
909 break;
910 default:
911 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, identityValue, "networkService", "localService", "localSystem", "other", "applicationPoolIdentity"));
912 break;
913 }
914 }
915 break;
916 case "IdleTimeout":
917 if (null == componentId)
918 {
919 this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
920 }
921
922 idleTimeout = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
923 break;
924 case "ManagedPipelineMode":
925 if (null == componentId)
926 {
927 this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
928 }
929
930 managedPipelineMode = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
931
932
933 if (!String.IsNullOrEmpty(managedPipelineMode))
934 {
935 switch (managedPipelineMode)
936 {
937 // In 3.5 we allowed lower case values (per camel case enum style), we now use formatted fields,
938 // so the value needs to match exactly what we pass in to IIS which uses pascal case.
939 case "classic":
940 managedPipelineMode = "Classic";
941 break;
942 case "integrated":
943 managedPipelineMode = "Integrated";
944 break;
945 case "Classic":
946 break;
947 case "Integrated":
948 break;
949 default:
950 if (!this.ParseHelper.ContainsProperty(managedPipelineMode))
951 {
952 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName, managedPipelineMode, "Classic", "Integrated"));
953 }
954 break;
955 }
956 }
957
958 break;
959 case "ManagedRuntimeVersion":
960 if (null == componentId)
961 {
962 this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
963 }
964
965 managedRuntimeVersion = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
966 break;
967 case "MaxCpuUsage":
968 if (null == componentId)
969 {
970 this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
971 }
972
973 maxCpuUsage = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, 100);
974 break;
975 case "MaxWorkerProcesses":
976 if (null == componentId)
977 {
978 this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
979 }
980
981 maxWorkerProcs = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
982 break;
983 case "Name":
984 name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
985 break;
986 case "PrivateMemory":
987 if (null == componentId)
988 {
989 this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
990 }
991
992 privateMemory = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, 4294967);
993 break;
994 case "QueueLimit":
995 if (null == componentId)
996 {
997 this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
998 }
999
1000 queueLimit = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
1001 break;
1002 case "RecycleMinutes":
1003 if (null == componentId)
1004 {
1005 this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
1006 }
1007
1008 recycleMinutes = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
1009 break;
1010 case "RecycleRequests":
1011 if (null == componentId)
1012 {
1013 this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
1014 }
1015
1016 recycleRequests = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
1017 break;
1018 case "RefreshCpu":
1019 if (null == componentId)
1020 {
1021 this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
1022 }
1023
1024 refreshCpu = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, int.MaxValue);
1025 break;
1026 case "User":
1027 if (null == componentId)
1028 {
1029 this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
1030 }
1031
1032 user = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
1033 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "User", user);
1034 break;
1035 case "VirtualMemory":
1036 if (null == componentId)
1037 {
1038 this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
1039 }
1040
1041 virtualMemory = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, 4294967);
1042 break;
1043 default:
1044 this.ParseHelper.UnexpectedAttribute(element, attrib);
1045 break;
1046 }
1047 }
1048 else
1049 {
1050 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
1051 }
1052 }
1053
1054 if (null == id)
1055 {
1056 id = this.ParseHelper.CreateIdentifier("iap", name, componentId, user);
1057 }
1058
1059 if (null == name)
1060 {
1061 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
1062 }
1063
1064 if (null == user && 8 == (attributes & 0x1F))
1065 {
1066 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "User", "Identity", "other"));
1067 }
1068
1069 if (null != user && 8 != (attributes & 0x1F))
1070 {
1071 this.Messaging.Write(ErrorMessages.IllegalAttributeValueWithoutOtherAttribute(sourceLineNumbers, element.Name.LocalName, "User", user, "Identity", "other"));
1072 }
1073
1074 cpuMon = maxCpuUsage.ToString(CultureInfo.InvariantCulture.NumberFormat);
1075 if (CompilerConstants.IntegerNotSet != refreshCpu)
1076 {
1077 cpuMon = String.Concat(cpuMon, ",", refreshCpu.ToString(CultureInfo.InvariantCulture.NumberFormat));
1078 if (CompilerConstants.IntegerNotSet != cpuAction)
1079 {
1080 cpuMon = String.Concat(cpuMon, ",", cpuAction.ToString(CultureInfo.InvariantCulture.NumberFormat));
1081 }
1082 }
1083
1084 foreach (var child in element.Elements())
1085 {
1086 if (this.Namespace == child.Name.Namespace)
1087 {
1088 switch (child.Name.LocalName)
1089 {
1090 case "RecycleTime":
1091 if (null == componentId)
1092 {
1093 var childSourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(child);
1094 this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, element.Name.LocalName));
1095 }
1096
1097 if (null == recycleTimes)
1098 {
1099 recycleTimes = this.ParseRecycleTimeElement(intermediate, section, child);
1100 }
1101 else
1102 {
1103 recycleTimes = String.Concat(recycleTimes, ",", this.ParseRecycleTimeElement(intermediate, section, child));
1104 }
1105 break;
1106 default:
1107 this.ParseHelper.UnexpectedElement(element, child);
1108 break;
1109 }
1110 }
1111 else
1112 {
1113 this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child);
1114 }
1115 }
1116
1117 if (null != componentId)
1118 {
1119 // Reference ConfigureIIs since nothing will happen without it
1120 this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
1121 }
1122
1123 if (!this.Messaging.EncounteredError)
1124 {
1125 var symbol = section.AddSymbol(new IIsAppPoolSymbol(sourceLineNumbers, id)
1126 {
1127 Name = name,
1128 ComponentRef = componentId,
1129 Attributes = attributes,
1130 UserRef = user,
1131 RecycleTimes = recycleTimes,
1132 CPUMon = cpuMon,
1133 ManagedRuntimeVersion = managedRuntimeVersion,
1134 ManagedPipelineMode = managedPipelineMode,
1135 });
1136
1137 if (CompilerConstants.IntegerNotSet != recycleMinutes)
1138 {
1139 symbol.RecycleMinutes = recycleMinutes;
1140 }
1141
1142 if (CompilerConstants.IntegerNotSet != recycleRequests)
1143 {
1144 symbol.RecycleRequests = recycleRequests;
1145 }
1146
1147 if (CompilerConstants.IntegerNotSet != idleTimeout)
1148 {
1149 symbol.IdleTimeout = idleTimeout;
1150 }
1151
1152 if (CompilerConstants.IntegerNotSet != queueLimit)
1153 {
1154 symbol.QueueLimit = queueLimit;
1155 }
1156
1157 if (CompilerConstants.IntegerNotSet != maxWorkerProcs)
1158 {
1159 symbol.MaxProc = maxWorkerProcs;
1160 }
1161
1162 if (CompilerConstants.IntegerNotSet != virtualMemory)
1163 {
1164 symbol.VirtualMemory = virtualMemory;
1165 }
1166
1167 if (CompilerConstants.IntegerNotSet != privateMemory)
1168 {
1169 symbol.PrivateMemory = privateMemory;
1170 }
1171 }
1172 }
1173
1174 /// <summary>
1175 /// Parses a web directory element.
1176 /// </summary>
1177 /// <param name="element">Element to parse.</param>
1178 /// <param name="componentId">Identifier for parent component.</param>
1179 /// <param name="parentWeb">Optional identifier for parent web site.</param>
1180 private void ParseWebDirElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string parentWeb)
1181 {
1182 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
1183 Identifier id = null;
1184 string dirProperties = null;
1185 string path = null;
1186 string application = null;
1187
1188 foreach (var attrib in element.Attributes())
1189 {
1190 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
1191 {
1192 switch (attrib.Name.LocalName)
1193 {
1194 case "Id":
1195 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
1196 break;
1197 case "DirProperties":
1198 dirProperties = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
1199 break;
1200 case "Path":
1201 path = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1202 break;
1203 case "WebApplication":
1204 application = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1205 break;
1206 case "WebSite":
1207 if (null != parentWeb)
1208 {
1209 this.Messaging.Write(IIsErrors.WebSiteAttributeUnderWebSite(sourceLineNumbers, element.Name.LocalName));
1210 }
1211
1212 parentWeb = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
1213 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebSite, parentWeb);
1214 break;
1215 default:
1216 this.ParseHelper.UnexpectedAttribute(element, attrib);
1217 break;
1218 }
1219 }
1220 else
1221 {
1222 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
1223 }
1224 }
1225
1226 if (null == id)
1227 {
1228 id = this.ParseHelper.CreateIdentifier("iwd", componentId, parentWeb, dirProperties, application);
1229 }
1230
1231 if (null == path)
1232 {
1233 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Path"));
1234 }
1235
1236 if (null == parentWeb)
1237 {
1238 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "WebSite"));
1239 }
1240
1241 foreach (var child in element.Elements())
1242 {
1243 if (this.Namespace == child.Name.Namespace)
1244 {
1245 var childSourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(child);
1246 switch (child.Name.LocalName)
1247 {
1248 case "WebApplication":
1249 if (null != application)
1250 {
1251 this.Messaging.Write(IIsErrors.WebApplicationAlreadySpecified(childSourceLineNumbers, element.Name.LocalName));
1252 }
1253
1254 application = this.ParseWebApplicationElement(intermediate, section, child);
1255 break;
1256 case "WebDirProperties":
1257 if (null == componentId)
1258 {
1259 this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
1260 }
1261
1262 string childWebDirProperties = this.ParseWebDirPropertiesElement(intermediate, section, child, componentId);
1263 if (null == dirProperties)
1264 {
1265 dirProperties = childWebDirProperties;
1266 }
1267 else
1268 {
1269 this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, child.Name.LocalName, "DirProperties", child.Name.LocalName));
1270 }
1271 break;
1272 default:
1273 this.ParseHelper.UnexpectedElement(element, child);
1274 break;
1275 }
1276 }
1277 else
1278 {
1279 this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child);
1280 }
1281 }
1282
1283 if (null == dirProperties)
1284 {
1285 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "DirProperties"));
1286 }
1287
1288 if (null != application)
1289 {
1290 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebApplication, application);
1291 }
1292
1293 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebDirProperties, dirProperties);
1294
1295 // Reference ConfigureIIs since nothing will happen without it
1296 this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
1297
1298 if (!this.Messaging.EncounteredError)
1299 {
1300 section.AddSymbol(new IIsWebDirSymbol(sourceLineNumbers, id)
1301 {
1302 ComponentRef = componentId,
1303 WebRef = parentWeb,
1304 Path = path,
1305 DirPropertiesRef = dirProperties,
1306 ApplicationRef = application,
1307 });
1308 }
1309 }
1310
1311 /// <summary>
1312 /// Parses a web directory properties element.
1313 /// </summary>
1314 /// <param name="element">Element to parse.</param>
1315 /// <returns>The identifier for this WebDirProperties.</returns>
1316 private string ParseWebDirPropertiesElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
1317 {
1318 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
1319 Identifier id = null;
1320 int access = 0;
1321 var accessSet = false;
1322 int accessSSLFlags = 0;
1323 var accessSSLFlagsSet = false;
1324 string anonymousUser = null;
1325 var aspDetailedError = YesNoType.NotSet;
1326 string authenticationProviders = null;
1327 int authorization = 0;
1328 var authorizationSet = false;
1329 string cacheControlCustom = null;
1330 var cacheControlMaxAge = CompilerConstants.LongNotSet;
1331 string defaultDocuments = null;
1332 string httpExpires = null;
1333 var iisControlledPassword = false;
1334 var index = YesNoType.NotSet;
1335 var logVisits = YesNoType.NotSet;
1336 var notCustomError = YesNoType.NotSet;
1337
1338 foreach (var attrib in element.Attributes())
1339 {
1340 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
1341 {
1342 switch (attrib.Name.LocalName)
1343 {
1344 case "Id":
1345 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
1346 break;
1347 case "AnonymousUser":
1348 anonymousUser = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
1349 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "User", anonymousUser);
1350 break;
1351 case "AspDetailedError":
1352 aspDetailedError = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
1353 break;
1354 case "AuthenticationProviders":
1355 authenticationProviders = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1356 break;
1357 case "CacheControlCustom":
1358 cacheControlCustom = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1359 break;
1360 case "CacheControlMaxAge":
1361 cacheControlMaxAge = this.ParseHelper.GetAttributeLongValue(sourceLineNumbers, attrib, 0, uint.MaxValue); // 4294967295 (uint.MaxValue) represents unlimited
1362 break;
1363 case "ClearCustomError":
1364 notCustomError = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
1365 break;
1366 case "DefaultDocuments":
1367 defaultDocuments = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1368 break;
1369 case "HttpExpires":
1370 httpExpires = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1371 break;
1372 case "IIsControlledPassword":
1373 iisControlledPassword = YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
1374 break;
1375 case "Index":
1376 index = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
1377 break;
1378 case "LogVisits":
1379 logVisits = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib);
1380 break;
1381
1382 // Access attributes
1383 case "Execute":
1384 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
1385 {
1386 access |= 4;
1387 }
1388 else
1389 {
1390 access &= ~4;
1391 }
1392 accessSet = true;
1393 break;
1394 case "Read":
1395 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
1396 {
1397 access |= 1;
1398 }
1399 else
1400 {
1401 access &= ~1;
1402 }
1403 accessSet = true;
1404 break;
1405 case "Script":
1406 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
1407 {
1408 access |= 512;
1409 }
1410 else
1411 {
1412 access &= ~512;
1413 }
1414 accessSet = true;
1415 break;
1416 case "Write":
1417 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
1418 {
1419 access |= 2;
1420 }
1421 else
1422 {
1423 access &= ~2;
1424 }
1425 accessSet = true;
1426 break;
1427
1428 // AccessSSL Attributes
1429 case "AccessSSL":
1430 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
1431 {
1432 accessSSLFlags |= 8;
1433 }
1434 else
1435 {
1436 accessSSLFlags &= ~8;
1437 }
1438 accessSSLFlagsSet = true;
1439 break;
1440 case "AccessSSL128":
1441 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
1442 {
1443 accessSSLFlags |= 256;
1444 }
1445 else
1446 {
1447 accessSSLFlags &= ~256;
1448 }
1449 accessSSLFlagsSet = true;
1450 break;
1451 case "AccessSSLMapCert":
1452 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
1453 {
1454 accessSSLFlags |= 128;
1455 }
1456 else
1457 {
1458 accessSSLFlags &= ~128;
1459 }
1460 accessSSLFlagsSet = true;
1461 break;
1462 case "AccessSSLNegotiateCert":
1463 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
1464 {
1465 accessSSLFlags |= 32;
1466 }
1467 else
1468 {
1469 accessSSLFlags &= ~32;
1470 }
1471 accessSSLFlagsSet = true;
1472 break;
1473 case "AccessSSLRequireCert":
1474 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
1475 {
1476 accessSSLFlags |= 64;
1477 }
1478 else
1479 {
1480 accessSSLFlags &= ~64;
1481 }
1482 accessSSLFlagsSet = true;
1483 break;
1484
1485 // Authorization attributes
1486 case "AnonymousAccess":
1487 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
1488 {
1489 authorization |= 1;
1490 }
1491 else
1492 {
1493 authorization &= ~1;
1494 }
1495 authorizationSet = true;
1496 break;
1497 case "BasicAuthentication":
1498 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
1499 {
1500 authorization |= 2;
1501 }
1502 else
1503 {
1504 authorization &= ~2;
1505 }
1506 authorizationSet = true;
1507 break;
1508 case "DigestAuthentication":
1509 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
1510 {
1511 authorization |= 16;
1512 }
1513 else
1514 {
1515 authorization &= ~16;
1516 }
1517 authorizationSet = true;
1518 break;
1519 case "PassportAuthentication":
1520 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
1521 {
1522 authorization |= 64;
1523 }
1524 else
1525 {
1526 authorization &= ~64;
1527 }
1528 authorizationSet = true;
1529 break;
1530 case "WindowsAuthentication":
1531 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
1532 {
1533 authorization |= 4;
1534 }
1535 else
1536 {
1537 authorization &= ~4;
1538 }
1539 authorizationSet = true;
1540 break;
1541 default:
1542 this.ParseHelper.UnexpectedAttribute(element, attrib);
1543 break;
1544 }
1545 }
1546 else
1547 {
1548 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
1549 }
1550 }
1551
1552 if (null == id)
1553 {
1554 if (null == componentId)
1555 {
1556 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Id"));
1557 id = Identifier.Invalid;
1558 }
1559 else
1560 {
1561 id = this.ParseHelper.CreateIdentifier("wdp", componentId);
1562 }
1563 }
1564
1565 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
1566
1567 if (!this.Messaging.EncounteredError)
1568 {
1569 var symbol = section.AddSymbol(new IIsWebDirPropertiesSymbol(sourceLineNumbers, id)
1570 {
1571 AnonymousUserRef = anonymousUser,
1572 IIsControlledPassword = iisControlledPassword ? 1 : 0,
1573 DefaultDoc = defaultDocuments,
1574 HttpExpires = httpExpires,
1575 CacheControlCustom = cacheControlCustom,
1576 });
1577
1578 if (accessSet)
1579 {
1580 symbol.Access = access;
1581 }
1582
1583 if (authorizationSet)
1584 {
1585 symbol.Authorization = authorization;
1586 }
1587
1588 if (YesNoType.NotSet != logVisits)
1589 {
1590 symbol.LogVisits = YesNoType.Yes == logVisits ? 1 : 0;
1591 }
1592
1593 if (YesNoType.NotSet != index)
1594 {
1595 symbol.Index = YesNoType.Yes == index ? 1 : 0;
1596 }
1597
1598 if (YesNoType.NotSet != aspDetailedError)
1599 {
1600 symbol.AspDetailedError = YesNoType.Yes == aspDetailedError ? 1 : 0;
1601 }
1602
1603 if (CompilerConstants.LongNotSet != cacheControlMaxAge)
1604 {
1605 symbol.CacheControlMaxAge = unchecked((int)cacheControlMaxAge);
1606 }
1607
1608 if (YesNoType.NotSet != notCustomError)
1609 {
1610 symbol.NoCustomError = YesNoType.Yes == notCustomError ? 1 : 0;
1611 }
1612
1613 if (accessSSLFlagsSet)
1614 {
1615 symbol.AccessSSLFlags = accessSSLFlags;
1616 }
1617
1618 if (null != authenticationProviders)
1619 {
1620 symbol.AuthenticationProviders = authenticationProviders;
1621 }
1622 }
1623
1624 return id?.Id;
1625 }
1626
1627 /// <summary>
1628 /// Parses a web error element.
1629 /// </summary>
1630 /// <param name="element">Element to parse.</param>
1631 /// <param name="parentType">Type of the parent.</param>
1632 /// <param name="parent">Id of the parent.</param>
1633 private void ParseWebErrorElement(Intermediate intermediate, IntermediateSection section, XElement element, WebErrorParentType parentType, string parent)
1634 {
1635 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
1636 var errorCode = CompilerConstants.IntegerNotSet;
1637 string file = null;
1638 string url = null;
1639 var subCode = CompilerConstants.IntegerNotSet;
1640
1641 foreach (var attrib in element.Attributes())
1642 {
1643 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
1644 {
1645 switch (attrib.Name.LocalName)
1646 {
1647 case "ErrorCode":
1648 errorCode = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 400, 599);
1649 break;
1650 case "File":
1651 file = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1652 break;
1653 case "SubCode":
1654 subCode = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, int.MaxValue);
1655 break;
1656 case "URL":
1657 url = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1658 break;
1659 default:
1660 this.ParseHelper.UnexpectedAttribute(element, attrib);
1661 break;
1662 }
1663 }
1664 else
1665 {
1666 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
1667 }
1668 }
1669
1670 if (CompilerConstants.IntegerNotSet == errorCode)
1671 {
1672 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "ErrorCode"));
1673 errorCode = CompilerConstants.IllegalInteger;
1674 }
1675
1676 if (CompilerConstants.IntegerNotSet == subCode)
1677 {
1678 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "SubCode"));
1679 subCode = CompilerConstants.IllegalInteger;
1680 }
1681
1682 if (String.IsNullOrEmpty(file) && String.IsNullOrEmpty(url))
1683 {
1684 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "File", "URL"));
1685 }
1686
1687 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
1688
1689 // Reference ConfigureIIs since nothing will happen without it
1690 this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
1691
1692 if (!this.Messaging.EncounteredError)
1693 {
1694 section.AddSymbol(new IIsWebErrorSymbol(sourceLineNumbers)
1695 {
1696 ErrorCode = errorCode,
1697 SubCode = subCode,
1698 ParentType = (int)parentType,
1699 ParentValue = parent,
1700 File = file,
1701 URL = url,
1702 });
1703 }
1704 }
1705
1706 /// <summary>
1707 /// Parses a web filter element.
1708 /// </summary>
1709 /// <param name="element">Element to parse.</param>
1710 /// <param name="componentId">Identifier of parent component.</param>
1711 /// <param name="parentWeb">Optional identifier of parent web site.</param>
1712 private void ParseWebFilterElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string parentWeb)
1713 {
1714 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
1715 Identifier id = null;
1716 string description = null;
1717 int flags = 0;
1718 var loadOrder = CompilerConstants.IntegerNotSet;
1719 string name = null;
1720 string path = null;
1721
1722 foreach (var attrib in element.Attributes())
1723 {
1724 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
1725 {
1726 switch (attrib.Name.LocalName)
1727 {
1728 case "Id":
1729 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
1730 break;
1731 case "Description":
1732 description = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1733 break;
1734 case "Flags":
1735 flags = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, int.MaxValue);
1736 break;
1737 case "LoadOrder":
1738 string loadOrderValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1739 if (0 < loadOrderValue.Length)
1740 {
1741 switch (loadOrderValue)
1742 {
1743 case "first":
1744 loadOrder = 0;
1745 break;
1746 case "last":
1747 loadOrder = -1;
1748 break;
1749 default:
1750 loadOrder = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, short.MaxValue);
1751 break;
1752 }
1753 }
1754 break;
1755 case "Name":
1756 name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1757 break;
1758 case "Path":
1759 path = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1760 break;
1761 case "WebSite":
1762 if (null != parentWeb)
1763 {
1764 this.Messaging.Write(IIsErrors.WebSiteAttributeUnderWebSite(sourceLineNumbers, element.Name.LocalName));
1765 }
1766
1767 parentWeb = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
1768 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebSite, parentWeb);
1769 break;
1770 default:
1771 this.ParseHelper.UnexpectedAttribute(element, attrib);
1772 break;
1773 }
1774 }
1775 else
1776 {
1777 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
1778 }
1779 }
1780
1781 if (null == id)
1782 {
1783 id = this.ParseHelper.CreateIdentifier("ifl", name, componentId, path, parentWeb);
1784 }
1785
1786 if (null == name)
1787 {
1788 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
1789 }
1790
1791 if (null == path)
1792 {
1793 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Path"));
1794 }
1795
1796 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
1797
1798 // Reference ConfigureIIs since nothing will happen without it
1799 this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
1800
1801 if (!this.Messaging.EncounteredError)
1802 {
1803 var symbol = section.AddSymbol(new IIsFilterSymbol(sourceLineNumbers, id)
1804 {
1805 Name = name,
1806 ComponentRef = componentId,
1807 Path = path,
1808 WebRef = parentWeb,
1809 Description = description,
1810 Flags = flags,
1811 });
1812
1813 if (CompilerConstants.IntegerNotSet != loadOrder)
1814 {
1815 symbol.LoadOrder = loadOrder;
1816 }
1817 }
1818 }
1819
1820 /// <summary>
1821 /// Parses web log element.
1822 /// </summary>
1823 /// <param name="element">Node to be parsed.</param>
1824 private void ParseWebLogElement(Intermediate intermediate, IntermediateSection section, XElement element)
1825 {
1826 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
1827 Identifier id = null;
1828 string type = null;
1829
1830 foreach (var attrib in element.Attributes())
1831 {
1832 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
1833 {
1834 switch (attrib.Name.LocalName)
1835 {
1836 case "Id":
1837 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
1838 break;
1839 case "Type":
1840 var typeValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1841 if (0 < typeValue.Length)
1842 {
1843 switch (typeValue)
1844 {
1845 case "IIS":
1846 type = "Microsoft IIS Log File Format";
1847 break;
1848 case "NCSA":
1849 type = "NCSA Common Log File Format";
1850 break;
1851 case "none":
1852 type = "none";
1853 break;
1854 case "ODBC":
1855 type = "ODBC Logging";
1856 break;
1857 case "W3C":
1858 type = "W3C Extended Log File Format";
1859 break;
1860 default:
1861 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Type", typeValue, "IIS", "NCSA", "none", "ODBC", "W3C"));
1862 break;
1863 }
1864 }
1865 break;
1866 default:
1867 this.ParseHelper.UnexpectedAttribute(element, attrib);
1868 break;
1869 }
1870 }
1871 else
1872 {
1873 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
1874 }
1875 }
1876
1877 if (null == id)
1878 {
1879 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Id"));
1880 }
1881
1882 if (null == type)
1883 {
1884 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Type"));
1885 }
1886
1887 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
1888
1889 if (!this.Messaging.EncounteredError)
1890 {
1891 section.AddSymbol(new IIsWebLogSymbol(sourceLineNumbers, id)
1892 {
1893 Format = type,
1894 });
1895 }
1896 }
1897
1898 /// <summary>
1899 /// Parses a web property element.
1900 /// </summary>
1901 /// <param name="element">Element to parse.</param>
1902 /// <param name="componentId">Identifier for parent component.</param>
1903 private void ParseWebPropertyElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
1904 {
1905 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
1906 Identifier id = null;
1907 string value = null;
1908
1909 foreach (var attrib in element.Attributes())
1910 {
1911 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
1912 {
1913 switch (attrib.Name.LocalName)
1914 {
1915 case "Id":
1916 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
1917 break;
1918 case "Value":
1919 value = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
1920 break;
1921 default:
1922 this.ParseHelper.UnexpectedAttribute(element, attrib);
1923 break;
1924 }
1925 }
1926 else
1927 {
1928 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
1929 }
1930 }
1931
1932 switch (id?.Id)
1933 {
1934 case "ETagChangeNumber":
1935 case "MaxGlobalBandwidth":
1936 // Must specify a value for these
1937 if (null == value)
1938 {
1939 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Value", "Id", id.Id));
1940 }
1941 break;
1942 case "IIs5IsolationMode":
1943 case "LogInUTF8":
1944 // Can't specify a value for these
1945 if (null != value)
1946 {
1947 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "Value", "Id", id.Id));
1948 }
1949 break;
1950 default:
1951 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Id", id?.Id, "ETagChangeNumber", "IIs5IsolationMode", "LogInUTF8", "MaxGlobalBandwidth"));
1952 break;
1953 }
1954
1955 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
1956
1957 // Reference ConfigureIIs since nothing will happen without it
1958 this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
1959
1960 if (!this.Messaging.EncounteredError)
1961 {
1962 section.AddSymbol(new IIsPropertySymbol(sourceLineNumbers, id)
1963 {
1964 ComponentRef = componentId,
1965 Attributes = 0,
1966 Value = value,
1967 });
1968 }
1969 }
1970
1971 /// <summary>
1972 /// Parses a web service extension element.
1973 /// </summary>
1974 /// <param name="element">Element to parse.</param>
1975 /// <param name="componentId">Identifier for parent component.</param>
1976 private void ParseWebServiceExtensionElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
1977 {
1978 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
1979 Identifier id = null;
1980 int attributes = 0;
1981 string description = null;
1982 string file = null;
1983 string group = null;
1984
1985 foreach (XAttribute attrib in element.Attributes())
1986 {
1987 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
1988 {
1989 switch (attrib.Name.LocalName)
1990 {
1991 case "Id":
1992 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
1993 break;
1994 case "Allow":
1995 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
1996 {
1997 attributes |= 1;
1998 }
1999 else
2000 {
2001 attributes &= ~1;
2002 }
2003 break;
2004 case "Description":
2005 description = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2006 break;
2007 case "File":
2008 file = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2009 break;
2010 case "Group":
2011 group = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2012 break;
2013 case "UIDeletable":
2014 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
2015 {
2016 attributes |= 2;
2017 }
2018 else
2019 {
2020 attributes &= ~2;
2021 }
2022 break;
2023 default:
2024 this.ParseHelper.UnexpectedAttribute(element, attrib);
2025 break;
2026 }
2027 }
2028 else
2029 {
2030 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
2031 }
2032 }
2033
2034 if (null == id)
2035 {
2036 id = this.ParseHelper.CreateIdentifier("iwe", componentId, file);
2037 }
2038
2039 if (null == file)
2040 {
2041 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "File"));
2042 }
2043
2044 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
2045
2046 // Reference ConfigureIIs since nothing will happen without it
2047 this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
2048
2049 if (!this.Messaging.EncounteredError)
2050 {
2051 section.AddSymbol(new IIsWebServiceExtensionSymbol(sourceLineNumbers, id)
2052 {
2053 ComponentRef = componentId,
2054 File = file,
2055 Description = description,
2056 Group = group,
2057 Attributes = attributes,
2058 });
2059 }
2060 }
2061
2062 /// <summary>
2063 /// Parses a web site element.
2064 /// </summary>
2065 /// <param name="element">Element to parse.</param>
2066 /// <param name="componentId">Optional identifier of parent component.</param>
2067 private void ParseWebSiteElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId)
2068 {
2069 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
2070 Identifier id = null;
2071 string application = null;
2072 int attributes = 0;
2073 var connectionTimeout = CompilerConstants.IntegerNotSet;
2074 string description = null;
2075 string directory = null;
2076 string dirProperties = null;
2077 string keyAddress = null;
2078 string log = null;
2079 string siteId = null;
2080 var sequence = CompilerConstants.IntegerNotSet;
2081 var state = CompilerConstants.IntegerNotSet;
2082
2083 foreach (var attrib in element.Attributes())
2084 {
2085 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
2086 {
2087 switch (attrib.Name.LocalName)
2088 {
2089 case "Id":
2090 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
2091 break;
2092 case "AutoStart":
2093 if (null == componentId)
2094 {
2095 this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
2096 }
2097
2098 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
2099 {
2100 state = 2;
2101 }
2102 else if (state != 1)
2103 {
2104 state = 0;
2105 }
2106 break;
2107 case "ConfigureIfExists":
2108 if (null == componentId)
2109 {
2110 this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
2111 }
2112
2113 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
2114 {
2115 attributes &= ~2;
2116 }
2117 else
2118 {
2119 attributes |= 2;
2120 }
2121 break;
2122 case "ConnectionTimeout":
2123 connectionTimeout = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 0, short.MaxValue);
2124 break;
2125 case "Description":
2126 description = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2127 break;
2128 case "Directory":
2129 directory = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
2130 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.Directory, directory);
2131 break;
2132 case "DirProperties":
2133 if (null == componentId)
2134 {
2135 this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
2136 }
2137
2138 dirProperties = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2139 break;
2140 case "SiteId":
2141 siteId = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2142 if ("*" == siteId)
2143 {
2144 siteId = "-1";
2145 }
2146 break;
2147 case "Sequence":
2148 sequence = this.ParseHelper.GetAttributeIntegerValue(sourceLineNumbers, attrib, 1, short.MaxValue);
2149 break;
2150 case "StartOnInstall":
2151 if (null == componentId)
2152 {
2153 this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
2154 }
2155
2156 // when state is set to 2 it implies 1, so don't set it to 1
2157 if (2 != state && YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
2158 {
2159 state = 1;
2160 }
2161 else if (2 != state)
2162 {
2163 state = 0;
2164 }
2165 break;
2166 case "WebApplication":
2167 if (null == componentId)
2168 {
2169 this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
2170 }
2171
2172 application = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2173 break;
2174 case "WebLog":
2175 if (null == componentId)
2176 {
2177 this.Messaging.Write(IIsErrors.IllegalAttributeWithoutComponent(sourceLineNumbers, element.Name.LocalName, attrib.Name.LocalName));
2178 }
2179
2180 log = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
2181 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebLog, log);
2182 break;
2183 default:
2184 this.ParseHelper.UnexpectedAttribute(element, attrib);
2185 break;
2186 }
2187 }
2188 else
2189 {
2190 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
2191 }
2192 }
2193
2194 if (null == id)
2195 {
2196 id = this.ParseHelper.CreateIdentifier("iws", description, componentId, siteId, application);
2197 }
2198
2199 if (null == description)
2200 {
2201 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Description"));
2202 }
2203
2204 if (null == directory && null != componentId)
2205 {
2206 this.Messaging.Write(IIsErrors.RequiredAttributeUnderComponent(sourceLineNumbers, element.Name.LocalName, "Directory"));
2207 }
2208
2209 foreach (var child in element.Elements())
2210 {
2211 if (this.Namespace == child.Name.Namespace)
2212 {
2213 var childSourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(child);
2214 switch (child.Name.LocalName)
2215 {
2216 case "CertificateRef":
2217 if (null == componentId)
2218 {
2219 this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
2220 }
2221
2222 this.ParseCertificateRefElement(intermediate, section, child, id?.Id);
2223 break;
2224 case "HttpHeader":
2225 if (null == componentId)
2226 {
2227 this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
2228 }
2229
2230 this.ParseHttpHeaderElement(intermediate, section, child, HttpHeaderParentType.WebSite, id?.Id);
2231 break;
2232 case "WebAddress":
2233 string address = this.ParseWebAddressElement(intermediate, section, child, id?.Id);
2234 if (null == keyAddress)
2235 {
2236 keyAddress = address;
2237 }
2238 break;
2239 case "WebApplication":
2240 if (null == componentId)
2241 {
2242 this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
2243 }
2244
2245 if (null != application)
2246 {
2247 this.Messaging.Write(IIsErrors.WebApplicationAlreadySpecified(childSourceLineNumbers, element.Name.LocalName));
2248 }
2249
2250 application = this.ParseWebApplicationElement(intermediate, section, child);
2251 break;
2252 case "WebDir":
2253 if (null == componentId)
2254 {
2255 this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
2256 }
2257
2258 this.ParseWebDirElement(intermediate, section, child, componentId, id?.Id);
2259 break;
2260 case "WebDirProperties":
2261 if (null == componentId)
2262 {
2263 this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
2264 }
2265
2266 string childWebDirProperties = this.ParseWebDirPropertiesElement(intermediate, section, child, componentId);
2267 if (null == dirProperties)
2268 {
2269 dirProperties = childWebDirProperties;
2270 }
2271 else
2272 {
2273 this.Messaging.Write(ErrorMessages.IllegalParentAttributeWhenNested(sourceLineNumbers, "WebSite", "DirProperties", child.Name.LocalName));
2274 }
2275 break;
2276 case "WebError":
2277 if (null == componentId)
2278 {
2279 this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
2280 }
2281
2282 this.ParseWebErrorElement(intermediate, section, child, WebErrorParentType.WebSite, id?.Id);
2283 break;
2284 case "WebFilter":
2285 if (null == componentId)
2286 {
2287 this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
2288 }
2289
2290 this.ParseWebFilterElement(intermediate, section, child, componentId, id?.Id);
2291 break;
2292 case "WebVirtualDir":
2293 if (null == componentId)
2294 {
2295 this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
2296 }
2297
2298 this.ParseWebVirtualDirElement(intermediate, section, child, componentId, id?.Id, null);
2299 break;
2300 case "MimeMap":
2301 this.ParseMimeMapElement(intermediate, section, child, id?.Id, MimeMapParentType.WebSite);
2302 break;
2303 default:
2304 this.ParseHelper.UnexpectedElement(element, child);
2305 break;
2306 }
2307 }
2308 else
2309 {
2310 this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child);
2311 }
2312 }
2313
2314
2315 if (null == keyAddress)
2316 {
2317 this.Messaging.Write(ErrorMessages.ExpectedElement(sourceLineNumbers, element.Name.LocalName, "WebAddress"));
2318 }
2319
2320 if (null != application)
2321 {
2322 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebApplication, application);
2323 }
2324
2325 if (null != dirProperties)
2326 {
2327 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebDirProperties, dirProperties);
2328 }
2329
2330 if (null != componentId)
2331 {
2332 // Reference ConfigureIIs since nothing will happen without it
2333 this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
2334 }
2335
2336 if (!this.Messaging.EncounteredError)
2337 {
2338 var symbol = section.AddSymbol(new IIsWebSiteSymbol(sourceLineNumbers, id)
2339 {
2340 ComponentRef = componentId,
2341 Description = description,
2342 DirectoryRef = directory,
2343 KeyAddressRef = keyAddress,
2344 DirPropertiesRef = dirProperties,
2345 ApplicationRef = application,
2346 LogRef = log,
2347 WebsiteId = siteId,
2348 });
2349
2350 if (CompilerConstants.IntegerNotSet != connectionTimeout)
2351 {
2352 symbol.ConnectionTimeout = connectionTimeout;
2353 }
2354
2355 if (CompilerConstants.IntegerNotSet != state)
2356 {
2357 symbol.State = state;
2358 }
2359
2360 if (0 != attributes)
2361 {
2362 symbol.Attributes = attributes;
2363 }
2364
2365 if (CompilerConstants.IntegerNotSet != sequence)
2366 {
2367 symbol.Sequence = sequence;
2368 }
2369 }
2370 }
2371
2372 /// <summary>
2373 /// Parses a HTTP Header element.
2374 /// </summary>
2375 /// <param name="element">Element to parse.</param>
2376 /// <param name="parentType">Type of the parent.</param>
2377 /// <param name="parent">Id of the parent.</param>
2378 private void ParseHttpHeaderElement(Intermediate intermediate, IntermediateSection section, XElement element, HttpHeaderParentType parentType, string parent)
2379 {
2380 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
2381 Identifier id = null;
2382 string headerName = null;
2383 string headerValue = null;
2384
2385 foreach (var attrib in element.Attributes())
2386 {
2387 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
2388 {
2389 switch (attrib.Name.LocalName)
2390 {
2391 case "Id":
2392 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
2393 break;
2394 case "Name":
2395 headerName = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2396 break;
2397 case "Value":
2398 headerValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2399 break;
2400 default:
2401 this.ParseHelper.UnexpectedAttribute(element, attrib);
2402 break;
2403 }
2404 }
2405 else
2406 {
2407 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
2408 }
2409 }
2410
2411 if (null == headerName)
2412 {
2413 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
2414 }
2415 else if (null == id)
2416 {
2417 id = this.ParseHelper.CreateIdentifierFromFilename(headerName);
2418 }
2419
2420 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
2421
2422 // Reference ConfigureIIs since nothing will happen without it
2423 this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
2424
2425 if (!this.Messaging.EncounteredError)
2426 {
2427 section.AddSymbol(new IIsHttpHeaderSymbol(sourceLineNumbers, id)
2428 {
2429 HttpHeader = id.Id,
2430 ParentType = (int)parentType,
2431 ParentValue = parent,
2432 Name = headerName,
2433 Value = headerValue,
2434 Attributes = 0,
2435 });
2436 }
2437 }
2438
2439 /// <summary>
2440 /// Parses a virtual directory element.
2441 /// </summary>
2442 /// <param name="element">Element to parse.</param>
2443 /// <param name="componentId">Identifier of parent component.</param>
2444 /// <param name="parentWeb">Identifier of parent web site.</param>
2445 /// <param name="parentAlias">Alias of the parent web site.</param>
2446 private void ParseWebVirtualDirElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string parentWeb, string parentAlias)
2447 {
2448 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
2449 Identifier id = null;
2450 string alias = null;
2451 string application = null;
2452 string directory = null;
2453 string dirProperties = null;
2454
2455 foreach (var attrib in element.Attributes())
2456 {
2457 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
2458 {
2459 switch (attrib.Name.LocalName)
2460 {
2461 case "Id":
2462 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
2463 break;
2464 case "Alias":
2465 alias = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2466 break;
2467 case "Directory":
2468 directory = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
2469 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.Directory, directory);
2470 break;
2471 case "DirProperties":
2472 dirProperties = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2473 break;
2474 case "WebApplication":
2475 application = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
2476 break;
2477 case "WebSite":
2478 if (null != parentWeb)
2479 {
2480 this.Messaging.Write(IIsErrors.WebSiteAttributeUnderWebSite(sourceLineNumbers, element.Name.LocalName));
2481 }
2482
2483 parentWeb = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
2484 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebSite, parentWeb);
2485 break;
2486 default:
2487 this.ParseHelper.UnexpectedAttribute(element, attrib);
2488 break;
2489 }
2490 }
2491 else
2492 {
2493 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
2494 }
2495 }
2496
2497 if (null == id)
2498 {
2499 id = this.ParseHelper.CreateIdentifier("wvd", alias, directory, dirProperties, application, parentWeb);
2500 }
2501
2502 if (null == alias)
2503 {
2504 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Alias"));
2505 }
2506 else if (-1 != alias.IndexOf("\\", StringComparison.Ordinal))
2507 {
2508 this.Messaging.Write(IIsErrors.IllegalCharacterInAttributeValue(sourceLineNumbers, element.Name.LocalName, "Alias", alias, '\\'));
2509 }
2510
2511 if (null == directory)
2512 {
2513 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Directory"));
2514 }
2515
2516 if (null == parentWeb)
2517 {
2518 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "WebSite"));
2519 }
2520
2521 if (null == componentId)
2522 {
2523 this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(sourceLineNumbers, element.Name.LocalName));
2524 }
2525
2526 if (null != parentAlias)
2527 {
2528 alias = String.Concat(parentAlias, "/", alias);
2529 }
2530
2531 foreach (var child in element.Elements())
2532 {
2533 if (this.Namespace == child.Name.Namespace)
2534 {
2535 var childSourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(child);
2536 switch (child.Name.LocalName)
2537 {
2538 case "WebApplication":
2539 if (null != application)
2540 {
2541 this.Messaging.Write(IIsErrors.WebApplicationAlreadySpecified(childSourceLineNumbers, element.Name.LocalName));
2542 }
2543
2544 application = this.ParseWebApplicationElement(intermediate, section, child);
2545 break;
2546 case "WebDirProperties":
2547 if (null == componentId)
2548 {
2549 this.Messaging.Write(IIsErrors.IllegalElementWithoutComponent(childSourceLineNumbers, child.Name.LocalName));
2550 }
2551
2552 string childWebDirProperties = this.ParseWebDirPropertiesElement(intermediate, section, child, componentId);
2553 if (null == dirProperties)
2554 {
2555 dirProperties = childWebDirProperties;
2556 }
2557 else
2558 {
2559 this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, child.Name.LocalName, "DirProperties", child.Name.LocalName));
2560 }
2561 break;
2562
2563 case "WebError":
2564 this.ParseWebErrorElement(intermediate, section, child, WebErrorParentType.WebVirtualDir, id?.Id);
2565 break;
2566 case "WebVirtualDir":
2567 this.ParseWebVirtualDirElement(intermediate, section, child, componentId, parentWeb, alias);
2568 break;
2569 case "HttpHeader":
2570 this.ParseHttpHeaderElement(intermediate, section, child, HttpHeaderParentType.WebVirtualDir, id?.Id);
2571 break;
2572 case "MimeMap":
2573 this.ParseMimeMapElement(intermediate, section, child, id?.Id, MimeMapParentType.WebVirtualDir);
2574 break;
2575 default:
2576 this.ParseHelper.UnexpectedElement(element, child);
2577 break;
2578 }
2579 }
2580 else
2581 {
2582 this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child);
2583 }
2584 }
2585
2586 if (null != dirProperties)
2587 {
2588 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebDirProperties, dirProperties);
2589 }
2590
2591 if (null != application)
2592 {
2593 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, IisSymbolDefinitions.IIsWebApplication, application);
2594 }
2595
2596 // Reference ConfigureIIs since nothing will happen without it
2597 this.AddReferenceToConfigureIIs(section, sourceLineNumbers);
2598
2599 if (!this.Messaging.EncounteredError)
2600 {
2601 section.AddSymbol(new IIsWebVirtualDirSymbol(sourceLineNumbers, id)
2602 {
2603 ComponentRef = componentId,
2604 WebRef = parentWeb,
2605 Alias = alias,
2606 DirectoryRef = directory,
2607 DirPropertiesRef = dirProperties,
2608 ApplicationRef = application,
2609 });
2610 }
2611 }
2612
2613 private void AddReferenceToConfigureIIs(IntermediateSection section, SourceLineNumber sourceLineNumbers)
2614 {
2615 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4ConfigureIIs", this.Context.Platform, CustomActionPlatforms.X86 | CustomActionPlatforms.X64 | CustomActionPlatforms.ARM64);
2616 }
2617 }
2618 }