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