summaryrefslogtreecommitdiff
path: root/src/tools/heat/IIsWebSiteHarvester.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/heat/IIsWebSiteHarvester.cs')
-rw-r--r--src/tools/heat/IIsWebSiteHarvester.cs439
1 files changed, 439 insertions, 0 deletions
diff --git a/src/tools/heat/IIsWebSiteHarvester.cs b/src/tools/heat/IIsWebSiteHarvester.cs
new file mode 100644
index 00000000..6e5e29c7
--- /dev/null
+++ b/src/tools/heat/IIsWebSiteHarvester.cs
@@ -0,0 +1,439 @@
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.Harvesters
4{
5 using System;
6 using System.DirectoryServices;
7 using System.Globalization;
8 using System.Runtime.InteropServices;
9 using WixToolset.Data;
10 using WixToolset.Harvesters.Data;
11 using WixToolset.Harvesters.Extensibility;
12 using IIs = WixToolset.Harvesters.Serialize.IIs;
13 using Wix = WixToolset.Harvesters.Serialize;
14
15 /// <summary>
16 /// The web site harvester for the WiX Toolset Internet Information Services Extension.
17 /// </summary>
18 public sealed class IIsWebSiteHarvester : BaseHarvesterExtension
19 {
20 /// <summary>
21 /// Harvest a WiX document.
22 /// </summary>
23 /// <param name="argument">The argument for harvesting.</param>
24 /// <returns>The harvested Fragment.</returns>
25 public override Wix.Fragment[] Harvest(string argument)
26 {
27 DirectoryHarvester directoryHarvester = new DirectoryHarvester();
28 directoryHarvester.Core = this.Core;
29 directoryHarvester.KeepEmptyDirectories = true;
30
31 IIsWebSiteHarvester iisWebSiteHarvester = new IIsWebSiteHarvester();
32 iisWebSiteHarvester.Core = this.Core;
33
34 IIs.WebSite webSite = iisWebSiteHarvester.HarvestWebSite(argument);
35
36 Wix.Component component = new Wix.Component();
37 component.AddChild(new Wix.CreateFolder());
38 component.AddChild(webSite);
39
40 this.Core.RootDirectory = webSite.Directory;
41 Wix.Directory directory = directoryHarvester.HarvestDirectory(webSite.Directory, true);
42 directory.AddChild(component);
43
44 Wix.Fragment fragment = new Wix.Fragment();
45 fragment.AddChild(directory);
46
47 return new Wix.Fragment[] { fragment };
48 }
49
50 /// <summary>
51 /// Harvest a web site.
52 /// </summary>
53 /// <param name="name">The name of the web site.</param>
54 /// <returns>The harvested web site.</returns>
55 public IIs.WebSite HarvestWebSite(string name)
56 {
57 try
58 {
59 DirectoryEntry directoryEntry = new DirectoryEntry("IIS://localhost/W3SVC");
60
61 foreach (DirectoryEntry childEntry in directoryEntry.Children)
62 {
63 if ("IIsWebServer" == childEntry.SchemaClassName)
64 {
65 if (String.Equals((string)childEntry.Properties["ServerComment"].Value, name, StringComparison.OrdinalIgnoreCase))
66 {
67 return this.HarvestWebSite(childEntry);
68 }
69 }
70 }
71 }
72 catch (COMException ce)
73 {
74 // 0x8007005 - access denied
75 // If we don't have permission to harvest a website, it's likely because we're on
76 // Vista or higher and aren't an Admin.
77 if ((0x80070005 == unchecked((uint)ce.ErrorCode)))
78 {
79 throw new WixException(HarvesterErrors.InsufficientPermissionHarvestWebSite());
80 }
81 // 0x80005000 - unknown error
82 else if ((0x80005000 == unchecked((uint)ce.ErrorCode)))
83 {
84 throw new WixException(HarvesterErrors.CannotHarvestWebSite());
85 }
86 }
87
88 throw new WixException(HarvesterErrors.WebSiteNotFound(name));
89 }
90
91 /// <summary>
92 /// Harvest a web site.
93 /// </summary>
94 /// <param name="webSiteEntry">The web site directory entry.</param>
95 /// <returns>The harvested web site.</returns>
96 private IIs.WebSite HarvestWebSite(DirectoryEntry webSiteEntry)
97 {
98 IIs.WebSite webSite = new IIs.WebSite();
99
100 foreach (string propertyName in webSiteEntry.Properties.PropertyNames)
101 {
102 PropertyValueCollection property = webSiteEntry.Properties[propertyName];
103 PropertyValueCollection parentProperty = webSiteEntry.Parent.Properties[propertyName];
104
105 if (null == parentProperty.Value || parentProperty.Value.ToString() != property.Value.ToString())
106 {
107 switch (propertyName)
108 {
109 case "SecureBindings":
110 IIs.WebAddress secureWebAddress = this.HarvestBindings(propertyName, property);
111 if (null != secureWebAddress)
112 {
113 webSite.AddChild(secureWebAddress);
114 }
115 break;
116 case "ServerBindings":
117 IIs.WebAddress webAddress = this.HarvestBindings(propertyName, property);
118 if (null != webAddress)
119 {
120 webSite.AddChild(webAddress);
121 }
122 break;
123 case "ServerComment":
124 webSite.Description = (string)property.Value;
125 break;
126 }
127 }
128 }
129
130 foreach (DirectoryEntry childEntry in webSiteEntry.Children)
131 {
132 switch (childEntry.SchemaClassName)
133 {
134 case "IIsFilters":
135 string loadOrder = (string)childEntry.Properties["FilterLoadOrder"].Value;
136 if (loadOrder.Length > 0)
137 {
138 string[] filterNames = loadOrder.Split(",".ToCharArray());
139
140 for (int i = 0; i < filterNames.Length; i++)
141 {
142 using (DirectoryEntry webFilterEntry = new DirectoryEntry(String.Concat(childEntry.Path, '/', filterNames[i])))
143 {
144 IIs.WebFilter webFilter = this.HarvestWebFilter(webFilterEntry);
145
146 webFilter.LoadOrder = (i + 1).ToString(CultureInfo.InvariantCulture);
147
148 webSite.AddChild(webFilter);
149 }
150 }
151 }
152 break;
153 case "IIsWebDirectory":
154 this.HarvestWebDirectory(childEntry, webSite);
155 break;
156 case "IIsWebVirtualDir":
157 foreach (string propertyName in childEntry.Properties.PropertyNames)
158 {
159 PropertyValueCollection property = childEntry.Properties[propertyName];
160
161 switch (propertyName)
162 {
163 case "Path":
164 webSite.Directory = (string)property.Value;
165 break;
166 }
167 }
168
169 IIs.WebDirProperties webDirProps = this.HarvestWebDirProperties(childEntry);
170 if (null != webDirProps)
171 {
172 webSite.AddChild(webDirProps);
173 }
174
175 foreach (DirectoryEntry child2Entry in childEntry.Children)
176 {
177 switch (child2Entry.SchemaClassName)
178 {
179 case "IIsWebDirectory":
180 this.HarvestWebDirectory(child2Entry, webSite);
181 break;
182 case "IIsWebVirtualDir":
183 this.HarvestWebVirtualDir(child2Entry, webSite);
184 break;
185 }
186 }
187 break;
188 }
189 }
190
191 return webSite;
192 }
193
194 /// <summary>
195 /// Harvest bindings.
196 /// </summary>
197 /// <param name="propertyName">The property name of the bindings property.</param>
198 /// <param name="bindingsProperty">The bindings property.</param>
199 /// <returns>The harvested bindings.</returns>
200 private IIs.WebAddress HarvestBindings(string propertyName, PropertyValueCollection bindingsProperty)
201 {
202 if (1 == bindingsProperty.Count)
203 {
204 IIs.WebAddress webAddress = new IIs.WebAddress();
205
206 string[] bindings = ((string)bindingsProperty[0]).Split(":".ToCharArray());
207
208 if (0 < bindings[0].Length)
209 {
210 webAddress.IP = bindings[0];
211 }
212
213 if (0 < bindings[1].Length)
214 {
215 webAddress.Port = bindings[1];
216 }
217
218 if (0 < bindings[2].Length)
219 {
220 webAddress.Header = bindings[2];
221 }
222
223 if ("SecureBindings" == propertyName)
224 {
225 webAddress.Secure = IIs.YesNoType.yes;
226 }
227
228 return webAddress;
229 }
230
231 return null;
232 }
233
234 /// <summary>
235 /// Harvest a web directory.
236 /// </summary>
237 /// <param name="webDirectoryEntry">The web directory directory entry.</param>
238 /// <param name="webSite">The parent web site.</param>
239 private void HarvestWebDirectory(DirectoryEntry webDirectoryEntry, IIs.WebSite webSite)
240 {
241 foreach (DirectoryEntry childEntry in webDirectoryEntry.Children)
242 {
243 switch (childEntry.SchemaClassName)
244 {
245 case "IIsWebDirectory":
246 this.HarvestWebDirectory(childEntry, webSite);
247 break;
248 case "IIsWebVirtualDir":
249 this.HarvestWebVirtualDir(childEntry, webSite);
250 break;
251 }
252 }
253
254 IIs.WebDirProperties webDirProperties = this.HarvestWebDirProperties(webDirectoryEntry);
255
256 if (null != webDirProperties)
257 {
258 IIs.WebDir webDir = new IIs.WebDir();
259
260 int indexOfRoot = webDirectoryEntry.Path.IndexOf("ROOT/", StringComparison.OrdinalIgnoreCase);
261 webDir.Path = webDirectoryEntry.Path.Substring(indexOfRoot + 5);
262
263 webDir.AddChild(webDirProperties);
264
265 webSite.AddChild(webDir);
266 }
267 }
268
269 /// <summary>
270 /// Harvest a web filter.
271 /// </summary>
272 /// <param name="webFilterEntry">The web filter directory entry.</param>
273 /// <returns>The harvested web filter.</returns>
274 private IIs.WebFilter HarvestWebFilter(DirectoryEntry webFilterEntry)
275 {
276 IIs.WebFilter webFilter = new IIs.WebFilter();
277
278 webFilter.Name = webFilterEntry.Name;
279
280 foreach (string propertyName in webFilterEntry.Properties.PropertyNames)
281 {
282 PropertyValueCollection property = webFilterEntry.Properties[propertyName];
283
284 switch (propertyName)
285 {
286 case "FilterDescription":
287 webFilter.Description = (string)property.Value;
288 break;
289 case "FilterFlags":
290 webFilter.Flags = (int)property.Value;
291 break;
292 case "FilterPath":
293 webFilter.Path = (string)property.Value;
294 break;
295 }
296 }
297
298 return webFilter;
299 }
300
301 /// <summary>
302 /// Harvest a web directory's properties.
303 /// </summary>
304 /// <param name="directoryEntry">The web directory directory entry.</param>
305 /// <returns>The harvested web directory's properties.</returns>
306 private IIs.WebDirProperties HarvestWebDirProperties(DirectoryEntry directoryEntry)
307 {
308 bool foundProperties = false;
309 IIs.WebDirProperties webDirProperties = new IIs.WebDirProperties();
310
311 // Cannot read properties for "iisadmin" site.
312 if (String.Equals("iisadmin", directoryEntry.Name, StringComparison.OrdinalIgnoreCase) &&
313 String.Equals("ROOT", directoryEntry.Parent.Name, StringComparison.OrdinalIgnoreCase))
314 {
315 return null;
316 }
317
318 foreach (string propertyName in directoryEntry.Properties.PropertyNames)
319 {
320 PropertyValueCollection property = directoryEntry.Properties[propertyName];
321 PropertyValueCollection parentProperty = directoryEntry.Parent.Properties[propertyName];
322
323 if (null == parentProperty.Value || parentProperty.Value.ToString() != property.Value.ToString())
324 {
325 switch (propertyName)
326 {
327 case "AccessFlags":
328 int access = (int)property.Value;
329
330 if (0x1 == (access & 0x1))
331 {
332 webDirProperties.Read = IIs.YesNoType.yes;
333 }
334
335 if (0x2 == (access & 0x2))
336 {
337 webDirProperties.Write = IIs.YesNoType.yes;
338 }
339
340 if (0x4 == (access & 0x4))
341 {
342 webDirProperties.Execute = IIs.YesNoType.yes;
343 }
344
345 if (0x200 == (access & 0x200))
346 {
347 webDirProperties.Script = IIs.YesNoType.yes;
348 }
349
350 foundProperties = true;
351 break;
352 case "AuthFlags":
353 int authorization = (int)property.Value;
354
355 if (0x1 == (authorization & 0x1))
356 {
357 webDirProperties.AnonymousAccess = IIs.YesNoType.yes;
358 }
359
360 if (0x2 == (authorization & 0x2))
361 {
362 webDirProperties.BasicAuthentication = IIs.YesNoType.yes;
363 }
364
365 if (0x4 == (authorization & 0x4))
366 {
367 webDirProperties.WindowsAuthentication = IIs.YesNoType.yes;
368 }
369
370 if (0x10 == (authorization & 0x10))
371 {
372 webDirProperties.DigestAuthentication = IIs.YesNoType.yes;
373 }
374
375 if (0x40 == (authorization & 0x40))
376 {
377 webDirProperties.PassportAuthentication = IIs.YesNoType.yes;
378 }
379
380 foundProperties = true;
381 break;
382 }
383 }
384 }
385
386 return foundProperties ? webDirProperties : null;
387 }
388
389 /// <summary>
390 /// Harvest a web virtual directory.
391 /// </summary>
392 /// <param name="webVirtualDirEntry">The web virtual directory directory entry.</param>
393 /// <param name="webSite">The parent web site.</param>
394 private void HarvestWebVirtualDir(DirectoryEntry webVirtualDirEntry, IIs.WebSite webSite)
395 {
396 IIs.WebVirtualDir webVirtualDir = new IIs.WebVirtualDir();
397
398 foreach (string propertyName in webVirtualDirEntry.Properties.PropertyNames)
399 {
400 PropertyValueCollection property = webVirtualDirEntry.Properties[propertyName];
401 PropertyValueCollection parentProperty = webVirtualDirEntry.Parent.Properties[propertyName];
402
403 if (null == parentProperty.Value || parentProperty.Value.ToString() != property.Value.ToString())
404 {
405 switch (propertyName)
406 {
407 case "Path":
408 webVirtualDir.Directory = (string)property.Value;
409 break;
410 }
411 }
412 }
413
414 int indexOfRoot = webVirtualDirEntry.Path.IndexOf("ROOT/", StringComparison.OrdinalIgnoreCase);
415 webVirtualDir.Alias = webVirtualDirEntry.Path.Substring(indexOfRoot + 5);
416
417 IIs.WebDirProperties webDirProps = this.HarvestWebDirProperties(webVirtualDirEntry);
418 if (webDirProps != null)
419 {
420 webVirtualDir.AddChild(webDirProps);
421 }
422
423 foreach (DirectoryEntry childEntry in webVirtualDirEntry.Children)
424 {
425 switch (childEntry.SchemaClassName)
426 {
427 case "IIsWebDirectory":
428 this.HarvestWebDirectory(childEntry, webSite);
429 break;
430 case "IIsWebVirtualDir":
431 this.HarvestWebVirtualDir(childEntry, webSite);
432 break;
433 }
434 }
435
436 webSite.AddChild(webVirtualDir);
437 }
438 }
439}