summaryrefslogtreecommitdiff
path: root/src/tools/heat/IIsWebSiteHarvester.cs
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2022-07-26 17:20:39 -0700
committerRob Mensching <rob@firegiant.com>2022-08-01 20:25:19 -0700
commita627ca9b720047e633a8fe72003ab9bee31006c5 (patch)
tree2bc8a924bb4141ab718e74d08f6459a0ffe8d573 /src/tools/heat/IIsWebSiteHarvester.cs
parent521eb3c9cf38823a2c4019abb85dc0b3200b92cb (diff)
downloadwix-a627ca9b720047e633a8fe72003ab9bee31006c5.tar.gz
wix-a627ca9b720047e633a8fe72003ab9bee31006c5.tar.bz2
wix-a627ca9b720047e633a8fe72003ab9bee31006c5.zip
Create WixToolset.Heat.nupkg to distribute heat.exe and Heat targets
Moves Heat functionality to the "tools" layer and packages it all up in WixToolset.Heat.nupkg for distribution in WiX v4. Completes 6838
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}