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