aboutsummaryrefslogtreecommitdiff
path: root/src/wixext
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2018-01-02 23:14:58 -0800
committerRob Mensching <rob@firegiant.com>2018-01-02 23:14:58 -0800
commit97b80191048b23f2e870c9d6a27e368ebaaf594d (patch)
treeabe72531843285feb9f6e4502b5896a165219e3e /src/wixext
parent3fbfb758d90a52c54fc75669d9029badcbeaf251 (diff)
downloadwix-97b80191048b23f2e870c9d6a27e368ebaaf594d.tar.gz
wix-97b80191048b23f2e870c9d6a27e368ebaaf594d.tar.bz2
wix-97b80191048b23f2e870c9d6a27e368ebaaf594d.zip
Initial code commit
Diffstat (limited to 'src/wixext')
-rw-r--r--src/wixext/FirewallCompiler.cs356
-rw-r--r--src/wixext/FirewallConstants.cs21
-rw-r--r--src/wixext/FirewallDecompiler.cs169
-rw-r--r--src/wixext/FirewallErrors.cs42
-rw-r--r--src/wixext/FirewallExtensionData.cs24
-rw-r--r--src/wixext/FirewallExtensionFactory.cs18
-rw-r--r--src/wixext/FirewallWindowsInstallerBackendExtension.cs26
-rw-r--r--src/wixext/Tuples/FirewallTupleDefinitions.cs31
-rw-r--r--src/wixext/Tuples/WixFirewallExceptionTuple.cs93
-rw-r--r--src/wixext/WixToolset.Firewall.wixext.csproj36
-rw-r--r--src/wixext/WixToolset.Firewall.wixext.targets11
-rw-r--r--src/wixext/firewall.xsd211
-rw-r--r--src/wixext/tables.xml28
13 files changed, 1066 insertions, 0 deletions
diff --git a/src/wixext/FirewallCompiler.cs b/src/wixext/FirewallCompiler.cs
new file mode 100644
index 00000000..0696b4b1
--- /dev/null
+++ b/src/wixext/FirewallCompiler.cs
@@ -0,0 +1,356 @@
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.Firewall
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 Firewall Extension.
14 /// </summary>
15 public sealed class FirewallCompiler : BaseCompilerExtension
16 {
17 public override XNamespace Namespace => "http://wixtoolset.org/schemas/v4/wxs/firewall";
18
19 /// <summary>
20 /// Processes an element for the Compiler.
21 /// </summary>
22 /// <param name="sourceLineNumbers">Source line number for the parent element.</param>
23 /// <param name="parentElement">Parent element of element to process.</param>
24 /// <param name="element">Element to process.</param>
25 /// <param name="contextValues">Extra information about the context in which this element is being parsed.</param>
26 public override void ParseElement(Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, IDictionary<string, string> context)
27 {
28 switch (parentElement.Name.LocalName)
29 {
30 case "File":
31 string fileId = context["FileId"];
32 string fileComponentId = context["ComponentId"];
33
34 switch (element.Name.LocalName)
35 {
36 case "FirewallException":
37 this.ParseFirewallExceptionElement(intermediate, section, element, fileComponentId, fileId);
38 break;
39 default:
40 this.ParseHelper.UnexpectedElement(parentElement, element);
41 break;
42 }
43 break;
44 case "Component":
45 string componentId = context["ComponentId"];
46
47 switch (element.Name.LocalName)
48 {
49 case "FirewallException":
50 this.ParseFirewallExceptionElement(intermediate, section, element, componentId, null);
51 break;
52 default:
53 this.ParseHelper.UnexpectedElement(parentElement, element);
54 break;
55 }
56 break;
57 default:
58 this.ParseHelper.UnexpectedElement(parentElement, element);
59 break;
60 }
61 }
62
63 /// <summary>
64 /// Parses a FirewallException element.
65 /// </summary>
66 /// <param name="element">The element to parse.</param>
67 /// <param name="componentId">Identifier of the component that owns this firewall exception.</param>
68 /// <param name="fileId">The file identifier of the parent element (null if nested under Component).</param>
69 private void ParseFirewallExceptionElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string fileId)
70 {
71 SourceLineNumber sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
72 Identifier id = null;
73 string name = null;
74 int attributes = 0;
75 string file = null;
76 string program = null;
77 string port = null;
78 string protocolValue = null;
79 int? protocol = null;
80 string profileValue = null;
81 int? profile = null;
82 string scope = null;
83 string remoteAddresses = null;
84 string description = null;
85
86 foreach (XAttribute attrib in element.Attributes())
87 {
88 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
89 {
90 switch (attrib.Name.LocalName)
91 {
92 case "Id":
93 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
94 break;
95 case "Name":
96 name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
97 break;
98 case "File":
99 if (null != fileId)
100 {
101 this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, "File", "File"));
102 }
103 else
104 {
105 file = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
106 }
107 break;
108 case "IgnoreFailure":
109 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
110 {
111 attributes |= 0x1; // feaIgnoreFailures
112 }
113 break;
114 case "Program":
115 if (null != fileId)
116 {
117 this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, "Program", "File"));
118 }
119 else
120 {
121 program = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
122 }
123 break;
124 case "Port":
125 port = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
126 break;
127 case "Protocol":
128 protocolValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
129 switch (protocolValue)
130 {
131 case "tcp":
132 protocol = FirewallConstants.NET_FW_IP_PROTOCOL_TCP;
133 break;
134 case "udp":
135 protocol = FirewallConstants.NET_FW_IP_PROTOCOL_UDP;
136 break;
137 default:
138 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Protocol", protocolValue, "tcp", "udp"));
139 break;
140 }
141 break;
142 case "Scope":
143 scope = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
144 switch (scope)
145 {
146 case "any":
147 remoteAddresses = "*";
148 break;
149 case "localSubnet":
150 remoteAddresses = "LocalSubnet";
151 break;
152 default:
153 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Scope", scope, "any", "localSubnet"));
154 break;
155 }
156 break;
157 case "Profile":
158 profileValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
159 switch (profileValue)
160 {
161 case "domain":
162 profile = FirewallConstants.NET_FW_PROFILE2_DOMAIN;
163 break;
164 case "private":
165 profile = FirewallConstants.NET_FW_PROFILE2_PRIVATE;
166 break;
167 case "public":
168 profile = FirewallConstants.NET_FW_PROFILE2_PUBLIC;
169 break;
170 case "all":
171 profile = FirewallConstants.NET_FW_PROFILE2_ALL;
172 break;
173 default:
174 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Profile", profileValue, "domain", "private", "public", "all"));
175 break;
176 }
177 break;
178 case "Description":
179 description = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
180 break;
181 default:
182 this.ParseHelper.UnexpectedAttribute(element, attrib);
183 break;
184 }
185 }
186 else
187 {
188 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
189 }
190 }
191
192 // parse RemoteAddress children
193 foreach (XElement child in element.Elements())
194 {
195 if (this.Namespace == child.Name.Namespace)
196 {
197 SourceLineNumber childSourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(child);
198 switch (child.Name.LocalName)
199 {
200 case "RemoteAddress":
201 if (null != scope)
202 {
203 this.Messaging.Write(FirewallErrors.IllegalRemoteAddressWithScopeAttribute(sourceLineNumbers));
204 }
205 else
206 {
207 this.ParseRemoteAddressElement(intermediate, section, child, ref remoteAddresses);
208 }
209 break;
210 default:
211 this.ParseHelper.UnexpectedElement(element, child);
212 break;
213 }
214 }
215 else
216 {
217 this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child);
218 }
219 }
220
221 // Id and Name are required
222 if (null == id)
223 {
224 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Id"));
225 }
226
227 if (null == name)
228 {
229 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
230 }
231
232 // Scope or child RemoteAddress(es) are required
233 if (null == remoteAddresses)
234 {
235 this.Messaging.Write(ErrorMessages.ExpectedAttributeOrElement(sourceLineNumbers, element.Name.LocalName, "Scope", "RemoteAddress"));
236 }
237
238 // can't have both Program and File
239 if (null != program && null != file)
240 {
241 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "File", "Program"));
242 }
243
244 // must be nested under File, have File or Program attributes, or have Port attribute
245 if (String.IsNullOrEmpty(fileId) && String.IsNullOrEmpty(file) && String.IsNullOrEmpty(program) && String.IsNullOrEmpty(port))
246 {
247 this.Messaging.Write(FirewallErrors.NoExceptionSpecified(sourceLineNumbers));
248 }
249
250 if (!this.Messaging.EncounteredError)
251 {
252 // at this point, File attribute and File parent element are treated the same
253 if (null != file)
254 {
255 fileId = file;
256 }
257
258 var row = this.ParseHelper.CreateRow(section, sourceLineNumbers, "WixFirewallException", id);
259 row.Set(1, name);
260 row.Set(2, remoteAddresses);
261
262 if (!String.IsNullOrEmpty(port))
263 {
264 row.Set(3, port);
265
266 if (!protocol.HasValue)
267 {
268 // default protocol is "TCP"
269 protocol = FirewallConstants.NET_FW_IP_PROTOCOL_TCP;
270 }
271 }
272
273 if (protocol.HasValue)
274 {
275 row.Set(4, protocol);
276 }
277
278 if (!String.IsNullOrEmpty(fileId))
279 {
280 row.Set(5, $"[#{fileId}]");
281 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "File", fileId);
282 }
283 else if (!String.IsNullOrEmpty(program))
284 {
285 row.Set(5, program);
286 }
287
288 if (CompilerConstants.IntegerNotSet != attributes)
289 {
290 row.Set(6, attributes);
291 }
292
293 // Default is "all"
294 row.Set(7, profile ?? FirewallConstants.NET_FW_PROFILE2_ALL);
295
296 row.Set(8, componentId);
297
298 row.Set(9, description);
299
300 if (this.Context.Platform == Platform.ARM)
301 {
302 // Ensure ARM version of the CA is referenced
303 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "CustomAction", "WixSchedFirewallExceptionsInstall_ARM");
304 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "CustomAction", "WixSchedFirewallExceptionsUninstall_ARM");
305 }
306 else
307 {
308 // All other supported platforms use x86
309 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "CustomAction", "WixSchedFirewallExceptionsInstall");
310 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, "CustomAction", "WixSchedFirewallExceptionsUninstall");
311 }
312 }
313 }
314
315 /// <summary>
316 /// Parses a RemoteAddress element
317 /// </summary>
318 /// <param name="element">The element to parse.</param>
319 private void ParseRemoteAddressElement(Intermediate intermediate, IntermediateSection section, XElement element, ref string remoteAddresses)
320 {
321 SourceLineNumber sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
322
323 // no attributes
324 foreach (XAttribute attrib in element.Attributes())
325 {
326 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
327 {
328 this.ParseHelper.UnexpectedAttribute(element, attrib);
329 }
330 else
331 {
332 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
333 }
334 }
335
336 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
337
338 string address = this.ParseHelper.GetTrimmedInnerText(element);
339 if (String.IsNullOrEmpty(address))
340 {
341 this.Messaging.Write(FirewallErrors.IllegalEmptyRemoteAddress(sourceLineNumbers));
342 }
343 else
344 {
345 if (String.IsNullOrEmpty(remoteAddresses))
346 {
347 remoteAddresses = address;
348 }
349 else
350 {
351 remoteAddresses = String.Concat(remoteAddresses, ",", address);
352 }
353 }
354 }
355 }
356}
diff --git a/src/wixext/FirewallConstants.cs b/src/wixext/FirewallConstants.cs
new file mode 100644
index 00000000..16caa5b4
--- /dev/null
+++ b/src/wixext/FirewallConstants.cs
@@ -0,0 +1,21 @@
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.Firewall
4{
5 using System;
6 using System.Collections.Generic;
7 using System.Text;
8
9 static class FirewallConstants
10 {
11 // from icftypes.h
12 public const int NET_FW_IP_PROTOCOL_TCP = 6;
13 public const int NET_FW_IP_PROTOCOL_UDP = 17;
14
15 // from icftypes.h
16 public const int NET_FW_PROFILE2_DOMAIN = 0x0001;
17 public const int NET_FW_PROFILE2_PRIVATE = 0x0002;
18 public const int NET_FW_PROFILE2_PUBLIC = 0x0004;
19 public const int NET_FW_PROFILE2_ALL = 0x7FFFFFFF;
20 }
21}
diff --git a/src/wixext/FirewallDecompiler.cs b/src/wixext/FirewallDecompiler.cs
new file mode 100644
index 00000000..b060f8e2
--- /dev/null
+++ b/src/wixext/FirewallDecompiler.cs
@@ -0,0 +1,169 @@
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.Firewall
4{
5#if TODO_CONSIDER_DECOMPILER
6 using System;
7 using System.Collections;
8 using System.Diagnostics;
9 using System.Globalization;
10 using WixToolset.Data;
11 using WixToolset.Extensibility;
12 using Firewall = WixToolset.Extensions.Serialize.Firewall;
13 using Wix = WixToolset.Data.Serialize;
14
15 /// <summary>
16 /// The decompiler for the WiX Toolset Firewall Extension.
17 /// </summary>
18 public sealed class FirewallDecompiler : DecompilerExtension
19 {
20 /// <summary>
21 /// Creates a decompiler for Firewall Extension.
22 /// </summary>
23 public FirewallDecompiler()
24 {
25 this.TableDefinitions = FirewallExtensionData.GetExtensionTableDefinitions();
26 }
27
28 /// <summary>
29 /// Get the extensions library to be removed.
30 /// </summary>
31 /// <param name="tableDefinitions">Table definitions for library.</param>
32 /// <returns>Library to remove from decompiled output.</returns>
33 public override Library GetLibraryToRemove(TableDefinitionCollection tableDefinitions)
34 {
35 return FirewallExtensionData.GetExtensionLibrary(tableDefinitions);
36 }
37
38 /// <summary>
39 /// Decompiles an extension table.
40 /// </summary>
41 /// <param name="table">The table to decompile.</param>
42 public override void DecompileTable(Table table)
43 {
44 switch (table.Name)
45 {
46 case "WixFirewallException":
47 this.DecompileWixFirewallExceptionTable(table);
48 break;
49 default:
50 base.DecompileTable(table);
51 break;
52 }
53 }
54
55 /// <summary>
56 /// Decompile the WixFirewallException table.
57 /// </summary>
58 /// <param name="table">The table to decompile.</param>
59 private void DecompileWixFirewallExceptionTable(Table table)
60 {
61 foreach (Row row in table.Rows)
62 {
63 Firewall.FirewallException fire = new Firewall.FirewallException();
64 fire.Id = (string)row[0];
65 fire.Name = (string)row[1];
66
67 string[] addresses = ((string)row[2]).Split(',');
68 if (1 == addresses.Length)
69 {
70 // special-case the Scope attribute values
71 if ("*" == addresses[0])
72 {
73 fire.Scope = Firewall.FirewallException.ScopeType.any;
74 }
75 else if ("LocalSubnet" == addresses[0])
76 {
77 fire.Scope = Firewall.FirewallException.ScopeType.localSubnet;
78 }
79 else
80 {
81 FirewallDecompiler.AddRemoteAddress(fire, addresses[0]);
82 }
83 }
84 else
85 {
86 foreach (string address in addresses)
87 {
88 FirewallDecompiler.AddRemoteAddress(fire, address);
89 }
90 }
91
92 if (!row.IsColumnEmpty(3))
93 {
94 fire.Port = (string)row[3];
95 }
96
97 if (!row.IsColumnEmpty(4))
98 {
99 switch (Convert.ToInt32(row[4]))
100 {
101 case FirewallConstants.NET_FW_IP_PROTOCOL_TCP:
102 fire.Protocol = Firewall.FirewallException.ProtocolType.tcp;
103 break;
104 case FirewallConstants.NET_FW_IP_PROTOCOL_UDP:
105 fire.Protocol = Firewall.FirewallException.ProtocolType.udp;
106 break;
107 }
108 }
109
110 if (!row.IsColumnEmpty(5))
111 {
112 fire.Program = (string)row[5];
113 }
114
115 if (!row.IsColumnEmpty(6))
116 {
117 int attr = Convert.ToInt32(row[6]);
118 if (0x1 == (attr & 0x1)) // feaIgnoreFailures
119 {
120 fire.IgnoreFailure = Firewall.YesNoType.yes;
121 }
122 }
123
124 if (!row.IsColumnEmpty(7))
125 {
126 switch (Convert.ToInt32(row[7]))
127 {
128 case FirewallConstants.NET_FW_PROFILE2_DOMAIN:
129 fire.Profile = Firewall.FirewallException.ProfileType.domain;
130 break;
131 case FirewallConstants.NET_FW_PROFILE2_PRIVATE:
132 fire.Profile = Firewall.FirewallException.ProfileType.@private;
133 break;
134 case FirewallConstants.NET_FW_PROFILE2_PUBLIC:
135 fire.Profile = Firewall.FirewallException.ProfileType.@public;
136 break;
137 case FirewallConstants.NET_FW_PROFILE2_ALL:
138 fire.Profile = Firewall.FirewallException.ProfileType.all;
139 break;
140 }
141 }
142
143 // Description column is new in v3.6
144 if (9 < row.Fields.Length && !row.IsColumnEmpty(9))
145 {
146 fire.Description = (string)row[9];
147 }
148
149 Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[8]);
150 if (null != component)
151 {
152 component.AddChild(fire);
153 }
154 else
155 {
156 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[6], "Component"));
157 }
158 }
159 }
160
161 private static void AddRemoteAddress(Firewall.FirewallException fire, string address)
162 {
163 Firewall.RemoteAddress remote = new Firewall.RemoteAddress();
164 remote.Content = address;
165 fire.AddChild(remote);
166 }
167 }
168#endif
169}
diff --git a/src/wixext/FirewallErrors.cs b/src/wixext/FirewallErrors.cs
new file mode 100644
index 00000000..3fff8c8d
--- /dev/null
+++ b/src/wixext/FirewallErrors.cs
@@ -0,0 +1,42 @@
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.Firewall
4{
5 using System.Resources;
6 using WixToolset.Data;
7
8 public static class FirewallErrors
9 {
10 public static Message IllegalRemoteAddressWithScopeAttribute(SourceLineNumber sourceLineNumbers)
11 {
12 return Message(sourceLineNumbers, Ids.IllegalRemoteAddressWithScopeAttribute, "The RemoteAddress element cannot be specified because its parent FirewallException already specified the Scope attribute. To use RemoteAddress elements, omit the Scope attribute.");
13 }
14
15 public static Message IllegalEmptyRemoteAddress(SourceLineNumber sourceLineNumbers)
16 {
17 return Message(sourceLineNumbers, Ids.IllegalEmptyRemoteAddress, "The RemoteAddress element's inner text cannot be an empty string or completely whitespace.");
18 }
19
20 public static Message NoExceptionSpecified(SourceLineNumber sourceLineNumbers)
21 {
22 return Message(sourceLineNumbers, Ids.NoExceptionSpecified, "The FirewallException element doesn't identify the target of the firewall exception. To create an application exception, nest the FirewallException element under a File element or provide a value for the File or Program attributes. To create a port exception, provide a value for the Port attribute.");
23 }
24
25 private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args)
26 {
27 return new Message(sourceLineNumber, MessageLevel.Error, (int)id, format, args);
28 }
29
30 private static Message Message(SourceLineNumber sourceLineNumber, Ids id, ResourceManager resourceManager, string resourceName, params object[] args)
31 {
32 return new Message(sourceLineNumber, MessageLevel.Error, (int)id, resourceManager, resourceName, args);
33 }
34
35 public enum Ids
36 {
37 IllegalRemoteAddressWithScopeAttribute = 6401,
38 IllegalEmptyRemoteAddress = 6402,
39 NoExceptionSpecified = 6403,
40 }
41 }
42}
diff --git a/src/wixext/FirewallExtensionData.cs b/src/wixext/FirewallExtensionData.cs
new file mode 100644
index 00000000..78939c4e
--- /dev/null
+++ b/src/wixext/FirewallExtensionData.cs
@@ -0,0 +1,24 @@
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.Firewall
4{
5 using WixToolset.Data;
6 using WixToolset.Extensibility;
7 using WixToolset.Firewall.Tuples;
8
9 public sealed class FirewallExtensionData : BaseExtensionData
10 {
11 public override string DefaultCulture => "en-US";
12
13 public override bool TryGetTupleDefinitionByName(string name, out IntermediateTupleDefinition tupleDefinition)
14 {
15 tupleDefinition = (name == FirewallTupleDefinitionNames.WixFirewallException) ? FirewallTupleDefinitions.WixFirewallException : null;
16 return tupleDefinition != null;
17 }
18
19 public override Intermediate GetLibrary(ITupleDefinitionCreator tupleDefinitions)
20 {
21 return Intermediate.Load(typeof(FirewallExtensionData).Assembly, "WixToolset.Firewall.firewall.wixlib", tupleDefinitions);
22 }
23 }
24}
diff --git a/src/wixext/FirewallExtensionFactory.cs b/src/wixext/FirewallExtensionFactory.cs
new file mode 100644
index 00000000..4594419d
--- /dev/null
+++ b/src/wixext/FirewallExtensionFactory.cs
@@ -0,0 +1,18 @@
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.Firewall
4{
5 using System;
6 using System.Collections.Generic;
7 using WixToolset.Extensibility;
8
9 public class FirewallExtensionFactory : BaseExtensionFactory
10 {
11 protected override IEnumerable<Type> ExtensionTypes => new[]
12 {
13 typeof(FirewallCompiler),
14 typeof(FirewallExtensionData),
15 typeof(FirewallWindowsInstallerBackendExtension),
16 };
17 }
18}
diff --git a/src/wixext/FirewallWindowsInstallerBackendExtension.cs b/src/wixext/FirewallWindowsInstallerBackendExtension.cs
new file mode 100644
index 00000000..a1c78f04
--- /dev/null
+++ b/src/wixext/FirewallWindowsInstallerBackendExtension.cs
@@ -0,0 +1,26 @@
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.Firewall
4{
5 using System.Linq;
6 using System.Xml;
7 using WixToolset.Data.WindowsInstaller;
8 using WixToolset.Extensibility;
9
10 public class FirewallWindowsInstallerBackendExtension : BaseWindowsInstallerBackendExtension
11 {
12 private static readonly TableDefinition[] Tables = LoadTables();
13
14 protected override TableDefinition[] TableDefinitionsForTuples => Tables;
15
16 private static TableDefinition[] LoadTables()
17 {
18 using (var resourceStream = typeof(FirewallWindowsInstallerBackendExtension).Assembly.GetManifestResourceStream("WixToolset.Firewall.tables.xml"))
19 using (var reader = XmlReader.Create(resourceStream))
20 {
21 var tables = TableDefinitionCollection.Load(reader);
22 return tables.ToArray();
23 }
24 }
25 }
26}
diff --git a/src/wixext/Tuples/FirewallTupleDefinitions.cs b/src/wixext/Tuples/FirewallTupleDefinitions.cs
new file mode 100644
index 00000000..79fc28cf
--- /dev/null
+++ b/src/wixext/Tuples/FirewallTupleDefinitions.cs
@@ -0,0 +1,31 @@
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.Firewall.Tuples
4{
5 using WixToolset.Data;
6
7 public static class FirewallTupleDefinitionNames
8 {
9 public static string WixFirewallException { get; } = "WixFirewallException";
10 }
11
12 public static partial class FirewallTupleDefinitions
13 {
14 public static readonly IntermediateTupleDefinition WixFirewallException = new IntermediateTupleDefinition(
15 FirewallTupleDefinitionNames.WixFirewallException,
16 new[]
17 {
18 new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.WixFirewallException), IntermediateFieldType.String),
19 new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Name), IntermediateFieldType.String),
20 new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.RemoteAddresses), IntermediateFieldType.String),
21 new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Port), IntermediateFieldType.String),
22 new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Protocol), IntermediateFieldType.Number),
23 new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Program), IntermediateFieldType.String),
24 new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Attributes), IntermediateFieldType.Number),
25 new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Profile), IntermediateFieldType.Number),
26 new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Component_), IntermediateFieldType.String),
27 new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Description), IntermediateFieldType.String),
28 },
29 typeof(WixFirewallExceptionTuple));
30 }
31}
diff --git a/src/wixext/Tuples/WixFirewallExceptionTuple.cs b/src/wixext/Tuples/WixFirewallExceptionTuple.cs
new file mode 100644
index 00000000..715a4b9b
--- /dev/null
+++ b/src/wixext/Tuples/WixFirewallExceptionTuple.cs
@@ -0,0 +1,93 @@
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.Firewall.Tuples
4{
5 using WixToolset.Data;
6
7 public enum WixFirewallExceptionTupleFields
8 {
9 WixFirewallException,
10 Name,
11 RemoteAddresses,
12 Port,
13 Protocol,
14 Program,
15 Attributes,
16 Profile,
17 Component_,
18 Description,
19 }
20
21 public class WixFirewallExceptionTuple : IntermediateTuple
22 {
23 public WixFirewallExceptionTuple() : base(FirewallTupleDefinitions.WixFirewallException, null, null)
24 {
25 }
26
27 public WixFirewallExceptionTuple(SourceLineNumber sourceLineNumber, Identifier id = null) : base(FirewallTupleDefinitions.WixFirewallException, sourceLineNumber, id)
28 {
29 }
30
31 public IntermediateField this[WixFirewallExceptionTupleFields index] => this.Fields[(int)index];
32
33 public string WixFirewallException
34 {
35 get => this.Fields[(int)WixFirewallExceptionTupleFields.WixFirewallException].AsString();
36 set => this.Set((int)WixFirewallExceptionTupleFields.WixFirewallException, value);
37 }
38
39 public string Name
40 {
41 get => this.Fields[(int)WixFirewallExceptionTupleFields.Name].AsString();
42 set => this.Set((int)WixFirewallExceptionTupleFields.Name, value);
43 }
44
45 public string RemoteAddresses
46 {
47 get => this.Fields[(int)WixFirewallExceptionTupleFields.RemoteAddresses].AsString();
48 set => this.Set((int)WixFirewallExceptionTupleFields.RemoteAddresses, value);
49 }
50
51 public string Port
52 {
53 get => this.Fields[(int)WixFirewallExceptionTupleFields.Port].AsString();
54 set => this.Set((int)WixFirewallExceptionTupleFields.Port, value);
55 }
56
57 public int Protocol
58 {
59 get => this.Fields[(int)WixFirewallExceptionTupleFields.Protocol].AsNumber();
60 set => this.Set((int)WixFirewallExceptionTupleFields.Protocol, value);
61 }
62
63 public string Program
64 {
65 get => this.Fields[(int)WixFirewallExceptionTupleFields.Program].AsString();
66 set => this.Set((int)WixFirewallExceptionTupleFields.Program, value);
67 }
68
69 public int Attributes
70 {
71 get => this.Fields[(int)WixFirewallExceptionTupleFields.Attributes].AsNumber();
72 set => this.Set((int)WixFirewallExceptionTupleFields.Attributes, value);
73 }
74
75 public int Profile
76 {
77 get => this.Fields[(int)WixFirewallExceptionTupleFields.Profile].AsNumber();
78 set => this.Set((int)WixFirewallExceptionTupleFields.Profile, value);
79 }
80
81 public string Component_
82 {
83 get => this.Fields[(int)WixFirewallExceptionTupleFields.Component_].AsString();
84 set => this.Set((int)WixFirewallExceptionTupleFields.Component_, value);
85 }
86
87 public string Description
88 {
89 get => this.Fields[(int)WixFirewallExceptionTupleFields.Description].AsString();
90 set => this.Set((int)WixFirewallExceptionTupleFields.Description, value);
91 }
92 }
93} \ No newline at end of file
diff --git a/src/wixext/WixToolset.Firewall.wixext.csproj b/src/wixext/WixToolset.Firewall.wixext.csproj
new file mode 100644
index 00000000..2d89911c
--- /dev/null
+++ b/src/wixext/WixToolset.Firewall.wixext.csproj
@@ -0,0 +1,36 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- 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. -->
3
4<Project Sdk="Microsoft.NET.Sdk">
5 <PropertyGroup>
6 <TargetFramework>netstandard2.0</TargetFramework>
7 <RootNamespace>WixToolset.Firewall</RootNamespace>
8 <Description>WiX Toolset Firewallity Extension</Description>
9 <Title>WiX Toolset Firewall Extension</Title>
10 <IsTool>true</IsTool>
11 <ContentTargetFolders>build</ContentTargetFolders>
12 </PropertyGroup>
13
14 <ItemGroup>
15 <Content Include="$(MSBuildThisFileName).targets" />
16 <Content Include="firewall.xsd" PackagePath="tools" />
17 <EmbeddedResource Include="tables.xml" />
18 <EmbeddedResource Include="$(OutputPath)..\firewall.wixlib" />
19 </ItemGroup>
20
21 <ItemGroup>
22 <ProjectReference Include="$(WixToolsetRootFolder)\Data\src\WixToolset.Data\WixToolset.Data.csproj" Condition=" '$(Configuration)' == 'Debug' And Exists('$(WixToolsetRootFolder)\Data\README.md') " />
23 <PackageReference Include="WixToolset.Data" Version="4.0.*" Condition=" '$(Configuration)' == 'Release' Or !Exists('$(WixToolsetRootFolder)\Data\README.md') " PrivateAssets="all" />
24
25 <ProjectReference Include="$(WixToolsetRootFolder)\Extensibility\src\WixToolset.Extensibility\WixToolset.Extensibility.csproj" Condition=" '$(Configuration)' == 'Debug' And Exists('$(WixToolsetRootFolder)\Extensibility\README.md') " />
26 <PackageReference Include="WixToolset.Extensibility" Version="4.0.*" Condition=" '$(Configuration)' == 'Release' Or !Exists('$(WixToolsetRootFolder)\Extensibility\README.md') " PrivateAssets="all" />
27 </ItemGroup>
28
29 <ItemGroup>
30 <ProjectReference Include="..\wixlib\firewall.wixproj" ReferenceOutputAssembly="false" />
31 </ItemGroup>
32
33 <ItemGroup>
34 <PackageReference Include="Nerdbank.GitVersioning" Version="2.1.7" PrivateAssets="all" />
35 </ItemGroup>
36</Project>
diff --git a/src/wixext/WixToolset.Firewall.wixext.targets b/src/wixext/WixToolset.Firewall.wixext.targets
new file mode 100644
index 00000000..c717450f
--- /dev/null
+++ b/src/wixext/WixToolset.Firewall.wixext.targets
@@ -0,0 +1,11 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- 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. -->
3
4<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
5 <PropertyGroup>
6 <WixToolsetFirewallWixextPath Condition=" '$(WixToolsetFirewallWixextPath)' == '' ">$(MSBuildThisFileDirectory)..\tools\WixToolset.Firewall.wixext.dll</WixToolsetFirewallWixextPath>
7 </PropertyGroup>
8 <ItemGroup>
9 <WixExtension Include="$(WixToolsetFirewallWixextPath)" />
10 </ItemGroup>
11</Project>
diff --git a/src/wixext/firewall.xsd b/src/wixext/firewall.xsd
new file mode 100644
index 00000000..d64aafef
--- /dev/null
+++ b/src/wixext/firewall.xsd
@@ -0,0 +1,211 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- 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. -->
3
4
5<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
6 xmlns:xse=" http://wixtoolset.org/schemas/XmlSchemaExtension"
7 xmlns:html="http://www.w3.org/1999/xhtml"
8 targetNamespace="http://wixtoolset.org/schemas/v4/wxs/firewall"
9 xmlns="http://wixtoolset.org/schemas/v4/wxs/firewall">
10 <xs:annotation>
11 <xs:documentation>
12 The source code schema for the WiX Toolset Firewall Extension.
13 </xs:documentation>
14 </xs:annotation>
15
16 <xs:import namespace="http://wixtoolset.org/schemas/v4/wxs" />
17
18 <xs:element name="FirewallException">
19 <xs:annotation>
20 <xs:documentation>
21 Registers an exception for a program or a specific port and protocol in the Windows Firewall
22 on Windows XP SP2, Windows Server 2003 SP1, and later. For more information about the Windows
23 Firewall, see <html:a href="http://msdn.microsoft.com/en-us/library/aa364679.aspx">
24 About Windows Firewall API</html:a>.
25 </xs:documentation>
26 <xs:appinfo>
27 <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="Component" />
28 <xse:parent namespace="http://wixtoolset.org/schemas/v4/wxs" ref="File" />
29 </xs:appinfo>
30 </xs:annotation>
31
32 <xs:complexType>
33 <xs:choice minOccurs="0" maxOccurs="unbounded">
34 <xs:annotation>
35 <xs:documentation>
36 Explicitly-listed remote addresses that this exception allows through the
37 firewall.
38 </xs:documentation>
39 </xs:annotation>
40 <xs:element ref="RemoteAddress" />
41 </xs:choice>
42
43 <xs:attribute name="Id" type="xs:string" use="required">
44 <xs:annotation>
45 <xs:documentation>
46 Unique ID of this firewall exception.
47 </xs:documentation>
48 </xs:annotation>
49 </xs:attribute>
50
51 <xs:attribute name="Name" type="xs:string" use="required">
52 <xs:annotation>
53 <xs:documentation>
54 Name of this firewall exception, visible to the user in the firewall
55 control panel.
56 </xs:documentation>
57 </xs:annotation>
58 </xs:attribute>
59
60 <xs:attribute name="Scope">
61 <xs:annotation>
62 <xs:documentation>
63 The scope of this firewall exception, which indicates whether incoming
64 connections can come from any computer including those on the Internet
65 or only those on the local network subnet. To more precisely specify
66 allowed remote address, specify a custom scope using RemoteAddress
67 child elements.
68 </xs:documentation>
69 </xs:annotation>
70 <xs:simpleType>
71 <xs:restriction base="xs:NMTOKEN">
72 <xs:enumeration value="any" />
73 <xs:enumeration value="localSubnet" />
74 </xs:restriction>
75 </xs:simpleType>
76 </xs:attribute>
77
78 <xs:attribute name="Port" type="xs:string">
79 <xs:annotation>
80 <xs:documentation>
81 Port to allow through the firewall for this exception.
82
83 If you use Port and also File or Program in the same
84 FirewallException element, the exception will fail to install on
85 Windows XP and Windows Server 2003. IgnoreFailure="yes" can be used to
86 ignore the resulting failure, but the exception will not be added.
87 </xs:documentation>
88 </xs:annotation>
89 </xs:attribute>
90
91 <xs:attribute name="Protocol">
92 <xs:annotation>
93 <xs:documentation>
94 IP protocol used for this firewall exception. If Port is defined,
95 "tcp" is assumed if the protocol is not specified.
96
97 If you use Protocol and also File or Program in the same
98 FirewallException element, the exception will fail to install on
99 Windows XP and Windows Server 2003. IgnoreFailure="yes" can be used to
100 ignore the resulting failure, but the exception will not be added.
101 </xs:documentation>
102 </xs:annotation>
103 <xs:simpleType>
104 <xs:restriction base="xs:NMTOKEN">
105 <xs:enumeration value="tcp" />
106 <xs:enumeration value="udp" />
107 </xs:restriction>
108 </xs:simpleType>
109 </xs:attribute>
110
111 <xs:attribute name="File" type="xs:string">
112 <xs:annotation>
113 <xs:documentation>
114 Identifier of a file to be granted access to all incoming ports and
115 protocols. If you use File, you cannot also use Program.
116
117 If you use File and also Port or Protocol in the same
118 FirewallException element, the exception will fail to install on
119 Windows XP and Windows Server 2003. IgnoreFailure="yes" can be used to
120 ignore the resulting failure, but the exception will not be added.
121 </xs:documentation>
122 </xs:annotation>
123 </xs:attribute>
124
125 <xs:attribute name="Program" type="xs:string">
126 <xs:annotation>
127 <xs:documentation>
128 Path to a target program to be granted access to all incoming ports and
129 protocols. Note that this is a formatted field, so you can use [#fileId]
130 syntax to refer to a file being installed. If you use Program, you cannot
131 also use File.
132
133 If you use Program and also Port or Protocol in the same
134 FirewallException element, the exception will fail to install on
135 Windows XP and Windows Server 2003. IgnoreFailure="yes" can be used to
136 ignore the resulting failure, but the exception will not be added.
137 </xs:documentation>
138 </xs:annotation>
139 </xs:attribute>
140
141 <xs:attribute name="IgnoreFailure" type="YesNoType">
142 <xs:annotation>
143 <xs:documentation>
144 If "yes," failures to register this firewall exception will be silently
145 ignored. If "no" (the default), failures will cause rollback.
146 </xs:documentation>
147 </xs:annotation>
148 </xs:attribute>
149
150 <xs:attribute name="Profile">
151 <xs:annotation>
152 <xs:documentation>
153 Profile type for this firewall exception. Default is "all".
154 </xs:documentation>
155 </xs:annotation>
156 <xs:simpleType>
157 <xs:restriction base="xs:NMTOKEN">
158 <xs:enumeration value="domain" />
159 <xs:enumeration value="private" />
160 <xs:enumeration value="public" />
161 <xs:enumeration value="all" />
162 </xs:restriction>
163 </xs:simpleType>
164 </xs:attribute>
165 <xs:attribute name="Description" type="xs:string">
166 <xs:annotation>
167 <xs:documentation>
168 Description for this firewall rule displayed in Windows Firewall manager in
169 Windows Vista and later.
170 </xs:documentation>
171 </xs:annotation>
172 </xs:attribute>
173 </xs:complexType>
174 </xs:element>
175
176 <xs:element name="RemoteAddress">
177 <xs:annotation>
178 <xs:documentation>
179 A remote address to which the port or program can listen. Address formats vary
180 based on the version of Windows and Windows Firewall the program is being installed
181 on. For Windows XP SP2 and Windows Server 2003 SP1, see
182 <html:a href="http://msdn.microsoft.com/en-us/library/aa365270.aspx">
183 RemoteAddresses Property</html:a>.
184 For Windows Vista and Windows Server 2008, see
185 <html:a href="http://msdn.microsoft.com/en-us/library/aa365366.aspx">
186 RemoteAddresses Property</html:a>.
187 </xs:documentation>
188 </xs:annotation>
189 <xs:complexType>
190 <xs:simpleContent>
191 <xs:extension base="xs:string">
192 <xs:annotation>
193 <xs:documentation>
194 A remote address.
195 </xs:documentation>
196 </xs:annotation>
197 </xs:extension>
198 </xs:simpleContent>
199 </xs:complexType>
200 </xs:element>
201
202 <xs:simpleType name="YesNoType">
203 <xs:annotation>
204 <xs:documentation>Values of this type will either be "yes" or "no".</xs:documentation>
205 </xs:annotation>
206 <xs:restriction base='xs:NMTOKEN'>
207 <xs:enumeration value="no"/>
208 <xs:enumeration value="yes"/>
209 </xs:restriction>
210 </xs:simpleType>
211</xs:schema>
diff --git a/src/wixext/tables.xml b/src/wixext/tables.xml
new file mode 100644
index 00000000..5b408b96
--- /dev/null
+++ b/src/wixext/tables.xml
@@ -0,0 +1,28 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- 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. -->
3
4
5<tableDefinitions xmlns="http://wixtoolset.org/schemas/v4/wi/tables">
6 <tableDefinition name="WixFirewallException">
7 <columnDefinition name="WixFirewallException" type="string" length="72" primaryKey="yes" modularize="column"
8 category="identifier" description="The primary key, a non-localized token." />
9 <columnDefinition name="Name" type="localized" length="255" nullable="yes" modularize="property"
10 category="formatted" description="Localizable display name." />
11 <columnDefinition name="RemoteAddresses" type="string" length="0" modularize="property"
12 category="formatted" description="Remote address to accept incoming connections from." />
13 <columnDefinition name="Port" type="string" length="0" modularize="property" nullable="yes"
14 category="formatted" minValue="1" description="Port number." />
15 <columnDefinition name="Protocol" type="number" length="1" nullable="yes"
16 category="integer" minValue="6" maxValue="17" description="Protocol (6=TCP; 17=UDP)." />
17 <columnDefinition name="Program" type="string" length="255" nullable="yes" modularize="property"
18 category="formatted" description="Exception for a program (formatted path name)." />
19 <columnDefinition name="Attributes" type="number" length="4" nullable="yes"
20 minValue="0" maxValue="65536" description="Vital=1" />
21 <columnDefinition name="Profile" type="number" length="4" nullable="no"
22 category="integer" minValue="1" maxValue="2147483647" description="Profile (1=domain; 2=private; 4=public; 2147483647=all)." />
23 <columnDefinition name="Component_" type="string" length="72" modularize="column"
24 keyTable="Component" keyColumn="1" category="identifier" description="Foreign key into the Component table referencing component that controls the firewall configuration."/>
25 <columnDefinition name="Description" type="string" length="255" nullable="yes"
26 category="formatted" description="Description displayed in Windows Firewall manager for this firewall rule."/>
27 </tableDefinition>
28</tableDefinitions>