aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchris_bednarski <Chris.Bednarski@minfos.com.au>2023-08-26 18:51:38 +1000
committerBob Arnson <github@bobs.org>2023-11-19 12:17:13 -0500
commit80e604761b4f43b9b79a4878fcae360b071a7c35 (patch)
tree9ca40a1d60a2ef1a5a1a426382356ae8b7cf9868
parent6e974490eeabc9a3728aa2fb9ad07e8a5adf4fb6 (diff)
downloadwix-80e604761b4f43b9b79a4878fcae360b071a7c35.tar.gz
wix-80e604761b4f43b9b79a4878fcae360b071a7c35.tar.bz2
wix-80e604761b4f43b9b79a4878fcae360b071a7c35.zip
change firewall extension table name to Wix5FirewallException
-rw-r--r--src/ext/Firewall/ca/firewall.cpp18
-rw-r--r--src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs160
-rw-r--r--src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/PackageComponents.wxs4
-rw-r--r--src/ext/Firewall/wixext/FirewallCompiler.cs40
-rw-r--r--src/ext/Firewall/wixext/FirewallDecompiler.cs40
-rw-r--r--src/ext/Firewall/wixext/FirewallTableDefinitions.cs6
-rw-r--r--src/ext/Firewall/wixlib/FirewallExtension_Platform.wxi32
-rw-r--r--src/ext/caDecor.h10
-rw-r--r--src/ext/caDecor.wxi6
-rw-r--r--src/test/msi/TestData/FirewallExtensionTests/ProtocolRules/ProtocolRules.wixproj13
-rw-r--r--src/test/msi/TestData/FirewallExtensionTests/ProtocolRules/product.wxs23
-rw-r--r--src/test/msi/TestData/FirewallExtensionTests/ScopeRules/ScopeRules.wixproj13
-rw-r--r--src/test/msi/TestData/FirewallExtensionTests/ScopeRules/product.wxs33
-rw-r--r--src/test/msi/WixToolsetTest.MsiE2E/FirewallExtensionTests.cs217
-rw-r--r--src/wix/WixToolset.Converters/WixConverter.cs4
15 files changed, 552 insertions, 67 deletions
diff --git a/src/ext/Firewall/ca/firewall.cpp b/src/ext/Firewall/ca/firewall.cpp
index 2a1ef825..eed6f9df 100644
--- a/src/ext/Firewall/ca/firewall.cpp
+++ b/src/ext/Firewall/ca/firewall.cpp
@@ -3,7 +3,7 @@
3#include "precomp.h" 3#include "precomp.h"
4 4
5LPCWSTR vcsFirewallExceptionQuery = 5LPCWSTR vcsFirewallExceptionQuery =
6 L"SELECT `Name`, `RemoteAddresses`, `Port`, `Protocol`, `Program`, `Attributes`, `Profile`, `Component_`, `Description`, `Direction` FROM `Wix4FirewallException`"; 6 L"SELECT `Name`, `RemoteAddresses`, `Port`, `Protocol`, `Program`, `Attributes`, `Profile`, `Component_`, `Description`, `Direction` FROM `Wix5FirewallException`";
7enum eFirewallExceptionQuery { feqName = 1, feqRemoteAddresses, feqPort, feqProtocol, feqProgram, feqAttributes, feqProfile, feqComponent, feqDescription, feqDirection }; 7enum eFirewallExceptionQuery { feqName = 1, feqRemoteAddresses, feqPort, feqProtocol, feqProgram, feqAttributes, feqProfile, feqComponent, feqDescription, feqDirection };
8enum eFirewallExceptionTarget { fetPort = 1, fetApplication, fetUnknown }; 8enum eFirewallExceptionTarget { fetPort = 1, fetApplication, fetUnknown };
9enum eFirewallExceptionAttributes { feaIgnoreFailures = 1 }; 9enum eFirewallExceptionAttributes { feaIgnoreFailures = 1 };
@@ -49,15 +49,15 @@ static UINT SchedFirewallExceptions(
49 ExitOnFailure(hr, "Failed to initialize"); 49 ExitOnFailure(hr, "Failed to initialize");
50 50
51 // anything to do? 51 // anything to do?
52 if (S_OK != WcaTableExists(L"Wix4FirewallException")) 52 if (S_OK != WcaTableExists(L"Wix5FirewallException"))
53 { 53 {
54 WcaLog(LOGMSG_STANDARD, "Wix4FirewallException table doesn't exist, so there are no firewall exceptions to configure."); 54 WcaLog(LOGMSG_STANDARD, "Wix5FirewallException table doesn't exist, so there are no firewall exceptions to configure.");
55 ExitFunction(); 55 ExitFunction();
56 } 56 }
57 57
58 // query and loop through all the firewall exceptions 58 // query and loop through all the firewall exceptions
59 hr = WcaOpenExecuteView(vcsFirewallExceptionQuery, &hView); 59 hr = WcaOpenExecuteView(vcsFirewallExceptionQuery, &hView);
60 ExitOnFailure(hr, "Failed to open view on Wix4FirewallException table"); 60 ExitOnFailure(hr, "Failed to open view on Wix5FirewallException table");
61 61
62 while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) 62 while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
63 { 63 {
@@ -150,7 +150,7 @@ static UINT SchedFirewallExceptions(
150 { 150 {
151 hr = S_OK; 151 hr = S_OK;
152 } 152 }
153 ExitOnFailure(hr, "failure occured while processing Wix4FirewallException table"); 153 ExitOnFailure(hr, "failure occured while processing Wix5FirewallException table");
154 154
155 // schedule ExecFirewallExceptions if there's anything to do 155 // schedule ExecFirewallExceptions if there's anything to do
156 if (pwzCustomActionData && *pwzCustomActionData) 156 if (pwzCustomActionData && *pwzCustomActionData)
@@ -159,16 +159,16 @@ static UINT SchedFirewallExceptions(
159 159
160 if (WCA_TODO_INSTALL == todoSched) 160 if (WCA_TODO_INSTALL == todoSched)
161 { 161 {
162 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackFirewallExceptionsInstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION); 162 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION5(L"RollbackFirewallExceptionsInstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
163 ExitOnFailure(hr, "failed to schedule firewall install exceptions rollback"); 163 ExitOnFailure(hr, "failed to schedule firewall install exceptions rollback");
164 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecFirewallExceptionsInstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION); 164 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION5(L"ExecFirewallExceptionsInstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
165 ExitOnFailure(hr, "failed to schedule firewall install exceptions execution"); 165 ExitOnFailure(hr, "failed to schedule firewall install exceptions execution");
166 } 166 }
167 else 167 else
168 { 168 {
169 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackFirewallExceptionsUninstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION); 169 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION5(L"RollbackFirewallExceptionsUninstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
170 ExitOnFailure(hr, "failed to schedule firewall uninstall exceptions rollback"); 170 ExitOnFailure(hr, "failed to schedule firewall uninstall exceptions rollback");
171 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecFirewallExceptionsUninstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION); 171 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION5(L"ExecFirewallExceptionsUninstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
172 ExitOnFailure(hr, "failed to schedule firewall uninstall exceptions execution"); 172 ExitOnFailure(hr, "failed to schedule firewall uninstall exceptions execution");
173 } 173 }
174 } 174 }
diff --git a/src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs b/src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs
index 06a877f6..7119e92d 100644
--- a/src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs
+++ b/src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs
@@ -18,17 +18,21 @@ namespace WixToolsetTest.Firewall
18 var folder = TestData.Get(@"TestData\UsingFirewall"); 18 var folder = TestData.Get(@"TestData\UsingFirewall");
19 var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder }); 19 var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder });
20 20
21 var results = build.BuildAndQuery(Build, "Wix4FirewallException", "CustomAction"); 21 var results = build.BuildAndQuery(Build, "Wix5FirewallException", "CustomAction");
22 WixAssert.CompareLineByLine(new[] 22 WixAssert.CompareLineByLine(new[]
23 { 23 {
24 "CustomAction:Wix4ExecFirewallExceptionsInstall_X86\t3073\tWix4FWCA_X86\tExecFirewallExceptions\t", 24 "CustomAction:Wix5ExecFirewallExceptionsInstall_X86\t3073\tWix5FWCA_X86\tExecFirewallExceptions\t",
25 "CustomAction:Wix4ExecFirewallExceptionsUninstall_X86\t3073\tWix4FWCA_X86\tExecFirewallExceptions\t", 25 "CustomAction:Wix5ExecFirewallExceptionsUninstall_X86\t3073\tWix5FWCA_X86\tExecFirewallExceptions\t",
26 "CustomAction:Wix4RollbackFirewallExceptionsInstall_X86\t3329\tWix4FWCA_X86\tExecFirewallExceptions\t", 26 "CustomAction:Wix5RollbackFirewallExceptionsInstall_X86\t3329\tWix5FWCA_X86\tExecFirewallExceptions\t",
27 "CustomAction:Wix4RollbackFirewallExceptionsUninstall_X86\t3329\tWix4FWCA_X86\tExecFirewallExceptions\t", 27 "CustomAction:Wix5RollbackFirewallExceptionsUninstall_X86\t3329\tWix5FWCA_X86\tExecFirewallExceptions\t",
28 "CustomAction:Wix4SchedFirewallExceptionsInstall_X86\t1\tWix4FWCA_X86\tSchedFirewallExceptionsInstall\t", 28 "CustomAction:Wix5SchedFirewallExceptionsInstall_X86\t1\tWix5FWCA_X86\tSchedFirewallExceptionsInstall\t",
29 "CustomAction:Wix4SchedFirewallExceptionsUninstall_X86\t1\tWix4FWCA_X86\tSchedFirewallExceptionsUninstall\t", 29 "CustomAction:Wix5SchedFirewallExceptionsUninstall_X86\t1\tWix5FWCA_X86\tSchedFirewallExceptionsUninstall\t",
30 "Wix4FirewallException:ExampleFirewall\tExampleApp\t*\t42\t6\t[#filNdJBJmq3UCUIwmXS8x21aAsvqzk]\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tAn app-based firewall exception\t1", 30 "Wix5FirewallException:ExampleFirewall\tExampleApp\t*\t42\t6\t[#filNdJBJmq3UCUIwmXS8x21aAsvqzk]\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tAn app-based firewall exception\t1",
31 "Wix4FirewallException:fex70IVsYNnbwiHQrEepmdTPKH8XYs\tExamplePort\tLocalSubnet\t42\t6\t\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tA port-based firewall exception\t2", 31 "Wix5FirewallException:fex_ZpDsnKyHlYiA24JHzvFxm3uLZ8\tExampleDefaultGatewayScope\tDefaultGateway\t4432\t6\t\t0\t2\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tdefaultGateway scope firewall exception\t1",
32 "Wix5FirewallException:fex6bkfWwpiRGI.wVFx0T7W4LXIHxU\tExampleDHCPScope\tdhcp\t\t211\ttest.exe\t0\t4\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tDHCP scope firewall exception\t1",
33 "Wix5FirewallException:fex70IVsYNnbwiHQrEepmdTPKH8XYs\tExamplePort\tLocalSubnet\t42\t6\t\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tA port-based firewall exception\t2",
34 "Wix5FirewallException:fexXxaXCXXFh.UxO_BjmZxi1B1du_Q\tExampleWINSScope\twins\t6573\t6\t\t0\t1\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tWINS scope firewall exception\t1",
35 "Wix5FirewallException:fexxY71H2ZBkPalv7uid1Yy4qaA_lA\tExampleDNSScope\tdns\t356\t17\t\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tDNS scope firewall exception\t1",
32 }, results); 36 }, results);
33 } 37 }
34 38
@@ -38,17 +42,21 @@ namespace WixToolsetTest.Firewall
38 var folder = TestData.Get(@"TestData\UsingFirewall"); 42 var folder = TestData.Get(@"TestData\UsingFirewall");
39 var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder }); 43 var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder });
40 44
41 var results = build.BuildAndQuery(BuildARM64, "Wix4FirewallException", "CustomAction"); 45 var results = build.BuildAndQuery(BuildARM64, "Wix5FirewallException", "CustomAction");
42 WixAssert.CompareLineByLine(new[] 46 WixAssert.CompareLineByLine(new[]
43 { 47 {
44 "CustomAction:Wix4ExecFirewallExceptionsInstall_A64\t3073\tWix4FWCA_A64\tExecFirewallExceptions\t", 48 "CustomAction:Wix5ExecFirewallExceptionsInstall_A64\t3073\tWix5FWCA_A64\tExecFirewallExceptions\t",
45 "CustomAction:Wix4ExecFirewallExceptionsUninstall_A64\t3073\tWix4FWCA_A64\tExecFirewallExceptions\t", 49 "CustomAction:Wix5ExecFirewallExceptionsUninstall_A64\t3073\tWix5FWCA_A64\tExecFirewallExceptions\t",
46 "CustomAction:Wix4RollbackFirewallExceptionsInstall_A64\t3329\tWix4FWCA_A64\tExecFirewallExceptions\t", 50 "CustomAction:Wix5RollbackFirewallExceptionsInstall_A64\t3329\tWix5FWCA_A64\tExecFirewallExceptions\t",
47 "CustomAction:Wix4RollbackFirewallExceptionsUninstall_A64\t3329\tWix4FWCA_A64\tExecFirewallExceptions\t", 51 "CustomAction:Wix5RollbackFirewallExceptionsUninstall_A64\t3329\tWix5FWCA_A64\tExecFirewallExceptions\t",
48 "CustomAction:Wix4SchedFirewallExceptionsInstall_A64\t1\tWix4FWCA_A64\tSchedFirewallExceptionsInstall\t", 52 "CustomAction:Wix5SchedFirewallExceptionsInstall_A64\t1\tWix5FWCA_A64\tSchedFirewallExceptionsInstall\t",
49 "CustomAction:Wix4SchedFirewallExceptionsUninstall_A64\t1\tWix4FWCA_A64\tSchedFirewallExceptionsUninstall\t", 53 "CustomAction:Wix5SchedFirewallExceptionsUninstall_A64\t1\tWix5FWCA_A64\tSchedFirewallExceptionsUninstall\t",
50 "Wix4FirewallException:ExampleFirewall\tExampleApp\t*\t42\t6\t[#filNdJBJmq3UCUIwmXS8x21aAsvqzk]\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tAn app-based firewall exception\t1", 54 "Wix5FirewallException:ExampleFirewall\tExampleApp\t*\t42\t6\t[#filNdJBJmq3UCUIwmXS8x21aAsvqzk]\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tAn app-based firewall exception\t1",
51 "Wix4FirewallException:fex70IVsYNnbwiHQrEepmdTPKH8XYs\tExamplePort\tLocalSubnet\t42\t6\t\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tA port-based firewall exception\t2", 55 "Wix5FirewallException:fex_ZpDsnKyHlYiA24JHzvFxm3uLZ8\tExampleDefaultGatewayScope\tDefaultGateway\t4432\t6\t\t0\t2\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tdefaultGateway scope firewall exception\t1",
56 "Wix5FirewallException:fex6bkfWwpiRGI.wVFx0T7W4LXIHxU\tExampleDHCPScope\tdhcp\t\t211\ttest.exe\t0\t4\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tDHCP scope firewall exception\t1",
57 "Wix5FirewallException:fex70IVsYNnbwiHQrEepmdTPKH8XYs\tExamplePort\tLocalSubnet\t42\t6\t\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tA port-based firewall exception\t2",
58 "Wix5FirewallException:fexXxaXCXXFh.UxO_BjmZxi1B1du_Q\tExampleWINSScope\twins\t6573\t6\t\t0\t1\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tWINS scope firewall exception\t1",
59 "Wix5FirewallException:fexxY71H2ZBkPalv7uid1Yy4qaA_lA\tExampleDNSScope\tdns\t356\t17\t\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tDNS scope firewall exception\t1",
52 }, results); 60 }, results);
53 } 61 }
54 62
@@ -71,8 +79,17 @@ namespace WixToolsetTest.Firewall
71 { 79 {
72 "FirewallException", 80 "FirewallException",
73 "FirewallException", 81 "FirewallException",
82 "FirewallException",
83 "FirewallException",
84 "FirewallException",
85 "FirewallException",
74 }, actual.Select(a => a.Name).ToArray()); 86 }, actual.Select(a => a.Name).ToArray());
87 }
75 88
89 [Fact]
90 public void RoundtripAttributesAreCorrectForApp()
91 {
92 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleApp");
76 WixAssert.CompareLineByLine(new[] 93 WixAssert.CompareLineByLine(new[]
77 { 94 {
78 "Id=ExampleFirewall", 95 "Id=ExampleFirewall",
@@ -85,8 +102,13 @@ namespace WixToolsetTest.Firewall
85 "Description=An app-based firewall exception", 102 "Description=An app-based firewall exception",
86 "Outbound=no", 103 "Outbound=no",
87 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall", 104 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
88 }, actual[0].Attributes); 105 }, actual.Attributes);
106 }
89 107
108 [Fact]
109 public void RoundtripAttributesAreCorrectForPort()
110 {
111 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExamplePort");
90 WixAssert.CompareLineByLine(new[] 112 WixAssert.CompareLineByLine(new[]
91 { 113 {
92 "Id=fex70IVsYNnbwiHQrEepmdTPKH8XYs", 114 "Id=fex70IVsYNnbwiHQrEepmdTPKH8XYs",
@@ -98,7 +120,79 @@ namespace WixToolsetTest.Firewall
98 "Description=A port-based firewall exception", 120 "Description=A port-based firewall exception",
99 "Outbound=yes", 121 "Outbound=yes",
100 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall", 122 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
101 }, actual[1].Attributes); 123 }, actual.Attributes);
124 }
125
126 [Fact]
127 public void RoundtripAttributesAreCorrectForDNSScope()
128 {
129 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleDNSScope");
130 WixAssert.CompareLineByLine(new[]
131 {
132 "Id=fexxY71H2ZBkPalv7uid1Yy4qaA_lA",
133 "Name=ExampleDNSScope",
134 "Scope=DNS",
135 "Port=356",
136 "Protocol=udp",
137 "Profile=all",
138 "Description=DNS scope firewall exception",
139 "Outbound=no",
140 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
141 }, actual.Attributes);
142 }
143
144 [Fact]
145 public void RoundtripAttributesAreCorrectForDHCPScope()
146 {
147 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleDHCPScope");
148 WixAssert.CompareLineByLine(new[]
149 {
150 "Id=fex6bkfWwpiRGI.wVFx0T7W4LXIHxU",
151 "Name=ExampleDHCPScope",
152 "Scope=DHCP",
153 "Protocol=211",
154 "Program=test.exe",
155 "Profile=public",
156 "Description=DHCP scope firewall exception",
157 "Outbound=no",
158 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall"
159 }, actual.Attributes);
160 }
161
162 [Fact]
163 public void RoundtripAttributesAreCorrectForWINSScope()
164 {
165 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleWINSScope");
166 WixAssert.CompareLineByLine(new[]
167 {
168 "Id=fexXxaXCXXFh.UxO_BjmZxi1B1du_Q",
169 "Name=ExampleWINSScope",
170 "Scope=WINS",
171 "Port=6573",
172 "Protocol=tcp",
173 "Profile=domain",
174 "Description=WINS scope firewall exception",
175 "Outbound=no",
176 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
177 }, actual.Attributes);
178 }
179
180 [Fact]
181 public void RoundtripAttributesAreCorrectForDefaultGatewayScope()
182 {
183 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleDefaultGatewayScope");
184 WixAssert.CompareLineByLine(new[]
185 {
186 "Id=fex_ZpDsnKyHlYiA24JHzvFxm3uLZ8",
187 "Name=ExampleDefaultGatewayScope",
188 "Scope=defaultGateway",
189 "Port=4432",
190 "Protocol=tcp",
191 "Profile=private",
192 "Description=defaultGateway scope firewall exception",
193 "Outbound=no",
194 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
195 }, actual.Attributes);
102 } 196 }
103 197
104 private static void Build(string[] args) 198 private static void Build(string[] args)
@@ -122,5 +216,31 @@ namespace WixToolsetTest.Firewall
122 var result = WixRunner.Execute(args); 216 var result = WixRunner.Execute(args);
123 result.AssertSuccess(); 217 result.AssertSuccess();
124 } 218 }
219 class AttributeVerifier
220 {
221 public string Name { get; set; }
222 public string[] Attributes { get; set; }
223 }
224
225 private static AttributeVerifier BuildAndDecompileAndBuild(string nameSpace, string ruleName)
226 {
227 var folder = TestData.Get(@"TestData", "UsingFirewall");
228 var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder });
229 var output = Path.Combine(folder, $"Firewall{ruleName}.xml");
230
231 build.BuildAndDecompileAndBuild(Build, Decompile, output);
232
233 var doc = XDocument.Load(output);
234 var actual = doc.Descendants()
235 .Where(e => e.Name.Namespace == nameSpace)
236 .Select(fe => new AttributeVerifier
237 {
238 Name = fe.Attributes().Single(a => a.Name.LocalName == "Name").Value,
239 Attributes = fe.Attributes().Select(a => $"{a.Name.LocalName}={a.Value}").ToArray()
240 })
241 .Single(av => av.Name == ruleName);
242
243 return actual;
244 }
125 } 245 }
126} 246}
diff --git a/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/PackageComponents.wxs b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/PackageComponents.wxs
index c712d895..957aa642 100644
--- a/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/PackageComponents.wxs
+++ b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/PackageComponents.wxs
@@ -12,6 +12,10 @@
12 </File> 12 </File>
13 13
14 <fw:FirewallException Description="A port-based firewall exception" Name="ExamplePort" Port="42" Outbound="yes" Scope="localSubnet" /> 14 <fw:FirewallException Description="A port-based firewall exception" Name="ExamplePort" Port="42" Outbound="yes" Scope="localSubnet" />
15 <fw:FirewallException Description="DNS scope firewall exception" Name="ExampleDNSScope" Port="356" Protocol="udp" Scope="DNS" />
16 <fw:FirewallException Description="DHCP scope firewall exception" Name="ExampleDHCPScope" Program="test.exe" Protocol="211" Scope="DHCP" Profile="public" />
17 <fw:FirewallException Description="WINS scope firewall exception" Name="ExampleWINSScope" Port="6573" Scope="WINS" Profile="domain"/>
18 <fw:FirewallException Description="defaultGateway scope firewall exception" Name="ExampleDefaultGatewayScope" Port="4432" Scope="defaultGateway" Profile="private" />
15 </Component> 19 </Component>
16 </ComponentGroup> 20 </ComponentGroup>
17 </Fragment> 21 </Fragment>
diff --git a/src/ext/Firewall/wixext/FirewallCompiler.cs b/src/ext/Firewall/wixext/FirewallCompiler.cs
index 19ee0b6d..ed49ba9c 100644
--- a/src/ext/Firewall/wixext/FirewallCompiler.cs
+++ b/src/ext/Firewall/wixext/FirewallCompiler.cs
@@ -135,7 +135,12 @@ namespace WixToolset.Firewall
135 protocol = FirewallConstants.NET_FW_IP_PROTOCOL_UDP; 135 protocol = FirewallConstants.NET_FW_IP_PROTOCOL_UDP;
136 break; 136 break;
137 default: 137 default:
138 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Protocol", protocolValue, "tcp", "udp")); 138 int parsedProtocol;
139 if (!Int32.TryParse(protocolValue, out parsedProtocol) || parsedProtocol > 255 || parsedProtocol < 0)
140 {
141 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Protocol", protocolValue, "tcp", "udp", "0-255"));
142 }
143 protocol = parsedProtocol;
139 break; 144 break;
140 } 145 }
141 break; 146 break;
@@ -149,8 +154,20 @@ namespace WixToolset.Firewall
149 case "localSubnet": 154 case "localSubnet":
150 remoteAddresses = "LocalSubnet"; 155 remoteAddresses = "LocalSubnet";
151 break; 156 break;
157 case "DNS":
158 remoteAddresses = "dns";
159 break;
160 case "DHCP":
161 remoteAddresses = "dhcp";
162 break;
163 case "WINS":
164 remoteAddresses = "wins";
165 break;
166 case "defaultGateway":
167 remoteAddresses = "DefaultGateway";
168 break;
152 default: 169 default:
153 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Scope", scope, "any", "localSubnet")); 170 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Scope", scope, "any", "localSubnet", "DNS", "DHCP", "WINS", "defaultGateway"));
154 break; 171 break;
155 } 172 }
156 break; 173 break;
@@ -251,6 +268,21 @@ namespace WixToolset.Firewall
251 this.Messaging.Write(FirewallErrors.NoExceptionSpecified(sourceLineNumbers)); 268 this.Messaging.Write(FirewallErrors.NoExceptionSpecified(sourceLineNumbers));
252 } 269 }
253 270
271 // Ports can only be specified if the protocol is TCP or UDP.
272 if (!String.IsNullOrEmpty(port) && protocol.HasValue)
273 {
274 switch(protocol.Value)
275 {
276 case FirewallConstants.NET_FW_IP_PROTOCOL_TCP:
277 case FirewallConstants.NET_FW_IP_PROTOCOL_UDP:
278 break;
279
280 default:
281 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "Port", "Protocol", protocol.Value.ToString()));
282 break;
283 }
284 }
285
254 if (!this.Messaging.EncounteredError) 286 if (!this.Messaging.EncounteredError)
255 { 287 {
256 // at this point, File attribute and File parent element are treated the same 288 // at this point, File attribute and File parent element are treated the same
@@ -300,8 +332,8 @@ namespace WixToolset.Firewall
300 symbol.Attributes = attributes; 332 symbol.Attributes = attributes;
301 } 333 }
302 334
303 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedFirewallExceptionsInstall", this.Context.Platform, CustomActionPlatforms.ARM64 | CustomActionPlatforms.X64 | CustomActionPlatforms.X86); 335 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix5SchedFirewallExceptionsInstall", this.Context.Platform, CustomActionPlatforms.ARM64 | CustomActionPlatforms.X64 | CustomActionPlatforms.X86);
304 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedFirewallExceptionsUninstall", this.Context.Platform, CustomActionPlatforms.ARM64 | CustomActionPlatforms.X64 | CustomActionPlatforms.X86); 336 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix5SchedFirewallExceptionsUninstall", this.Context.Platform, CustomActionPlatforms.ARM64 | CustomActionPlatforms.X64 | CustomActionPlatforms.X86);
305 } 337 }
306 } 338 }
307 339
diff --git a/src/ext/Firewall/wixext/FirewallDecompiler.cs b/src/ext/Firewall/wixext/FirewallDecompiler.cs
index 69f2c3f4..9ddd8a9a 100644
--- a/src/ext/Firewall/wixext/FirewallDecompiler.cs
+++ b/src/ext/Firewall/wixext/FirewallDecompiler.cs
@@ -32,7 +32,7 @@ namespace WixToolset.Firewall
32 { 32 {
33 switch (table.Name) 33 switch (table.Name)
34 { 34 {
35 case "Wix4FirewallException": 35 case "Wix5FirewallException":
36 this.DecompileWixFirewallExceptionTable(table); 36 this.DecompileWixFirewallExceptionTable(table);
37 break; 37 break;
38 default: 38 default:
@@ -69,18 +69,29 @@ namespace WixToolset.Firewall
69 string[] addresses = ((string)row[2]).Split(','); 69 string[] addresses = ((string)row[2]).Split(',');
70 if (addresses.Length == 1) 70 if (addresses.Length == 1)
71 { 71 {
72 // special-case the Scope attribute values 72 switch(addresses[0])
73 if (addresses[0] == "*")
74 { 73 {
75 firewallException.Add(new XAttribute("Scope", "any")); 74 case "*":
76 } 75 firewallException.Add(new XAttribute("Scope", "any"));
77 else if (addresses[0] == "LocalSubnet") 76 break;
78 { 77 case "LocalSubnet":
79 firewallException.Add(new XAttribute("Scope", "localSubnet")); 78 firewallException.Add(new XAttribute("Scope", "localSubnet"));
80 } 79 break;
81 else 80 case "dns":
82 { 81 firewallException.Add(new XAttribute("Scope", "DNS"));
83 FirewallDecompiler.AddRemoteAddress(firewallException, addresses[0]); 82 break;
83 case "dhcp":
84 firewallException.Add(new XAttribute("Scope", "DHCP"));
85 break;
86 case "wins":
87 firewallException.Add(new XAttribute("Scope", "WINS"));
88 break;
89 case "DefaultGateway":
90 firewallException.Add(new XAttribute("Scope", "defaultGateway"));
91 break;
92 default:
93 FirewallDecompiler.AddRemoteAddress(firewallException, addresses[0]);
94 break;
84 } 95 }
85 } 96 }
86 else 97 else
@@ -107,6 +118,9 @@ namespace WixToolset.Firewall
107 case FirewallConstants.NET_FW_IP_PROTOCOL_UDP: 118 case FirewallConstants.NET_FW_IP_PROTOCOL_UDP:
108 firewallException.Add(new XAttribute("Protocol", "udp")); 119 firewallException.Add(new XAttribute("Protocol", "udp"));
109 break; 120 break;
121 default:
122 firewallException.Add(new XAttribute("Protocol", row[4]));
123 break;
110 } 124 }
111 } 125 }
112 126
@@ -183,7 +197,7 @@ namespace WixToolset.Firewall
183 /// <param name="tables">Collection of all tables.</param> 197 /// <param name="tables">Collection of all tables.</param>
184 private void FinalizeFirewallExceptionTable(TableIndexedCollection tables) 198 private void FinalizeFirewallExceptionTable(TableIndexedCollection tables)
185 { 199 {
186 if (tables.TryGetTable("Wix4FirewallException", out var firewallExceptionTable)) 200 if (tables.TryGetTable("Wix5FirewallException", out var firewallExceptionTable))
187 { 201 {
188 foreach (var row in firewallExceptionTable.Rows) 202 foreach (var row in firewallExceptionTable.Rows)
189 { 203 {
diff --git a/src/ext/Firewall/wixext/FirewallTableDefinitions.cs b/src/ext/Firewall/wixext/FirewallTableDefinitions.cs
index 04918f5f..26dedbf1 100644
--- a/src/ext/Firewall/wixext/FirewallTableDefinitions.cs
+++ b/src/ext/Firewall/wixext/FirewallTableDefinitions.cs
@@ -7,15 +7,15 @@ namespace WixToolset.Firewall
7 public static class FirewallTableDefinitions 7 public static class FirewallTableDefinitions
8 { 8 {
9 public static readonly TableDefinition WixFirewallException = new TableDefinition( 9 public static readonly TableDefinition WixFirewallException = new TableDefinition(
10 "Wix4FirewallException", 10 "Wix5FirewallException",
11 FirewallSymbolDefinitions.WixFirewallException, 11 FirewallSymbolDefinitions.WixFirewallException,
12 new[] 12 new[]
13 { 13 {
14 new ColumnDefinition("Wix4FirewallException", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "The primary key, a non-localized token.", modularizeType: ColumnModularizeType.Column), 14 new ColumnDefinition("Wix5FirewallException", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "The primary key, a non-localized token.", modularizeType: ColumnModularizeType.Column),
15 new ColumnDefinition("Name", ColumnType.Localized, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Localizable display name.", modularizeType: ColumnModularizeType.Property), 15 new ColumnDefinition("Name", ColumnType.Localized, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Localizable display name.", modularizeType: ColumnModularizeType.Property),
16 new ColumnDefinition("RemoteAddresses", ColumnType.String, 0, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Remote address to accept incoming connections from.", modularizeType: ColumnModularizeType.Property), 16 new ColumnDefinition("RemoteAddresses", ColumnType.String, 0, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Remote address to accept incoming connections from.", modularizeType: ColumnModularizeType.Property),
17 new ColumnDefinition("Port", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, minValue: 1, description: "Port number.", modularizeType: ColumnModularizeType.Property), 17 new ColumnDefinition("Port", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, minValue: 1, description: "Port number.", modularizeType: ColumnModularizeType.Property),
18 new ColumnDefinition("Protocol", ColumnType.Number, 1, primaryKey: false, nullable: true, ColumnCategory.Integer, minValue: 6, maxValue: 17, description: "Protocol (6=TCP; 17=UDP)."), 18 new ColumnDefinition("Protocol", ColumnType.Number, 1, primaryKey: false, nullable: true, ColumnCategory.Integer, minValue: 0, maxValue: 255, description: "Protocol (6=TCP; 17=UDP). https://www.iana.org/assignments/protocol-numbers"),
19 new ColumnDefinition("Program", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Exception for a program (formatted path name).", modularizeType: ColumnModularizeType.Property), 19 new ColumnDefinition("Program", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Exception for a program (formatted path name).", modularizeType: ColumnModularizeType.Property),
20 new ColumnDefinition("Attributes", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Vital=1"), 20 new ColumnDefinition("Attributes", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Vital=1"),
21 new ColumnDefinition("Profile", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Integer, minValue: 1, maxValue: 2147483647, description: "Profile (1=domain; 2=private; 4=public; 2147483647=all)."), 21 new ColumnDefinition("Profile", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Integer, minValue: 1, maxValue: 2147483647, description: "Profile (1=domain; 2=private; 4=public; 2147483647=all)."),
diff --git a/src/ext/Firewall/wixlib/FirewallExtension_Platform.wxi b/src/ext/Firewall/wixlib/FirewallExtension_Platform.wxi
index ae02bcd0..736a54b0 100644
--- a/src/ext/Firewall/wixlib/FirewallExtension_Platform.wxi
+++ b/src/ext/Firewall/wixlib/FirewallExtension_Platform.wxi
@@ -6,32 +6,32 @@
6 <Fragment> 6 <Fragment>
7 <UIRef Id="WixFirewallErrors" /> 7 <UIRef Id="WixFirewallErrors" />
8 <UI> 8 <UI>
9 <ProgressText Action="$(var.Prefix)SchedFirewallExceptionsInstall$(var.Suffix)" Message="!(loc.WixSchedFirewallExceptionsInstall)" /> 9 <ProgressText Action="$(var.Prefix5)SchedFirewallExceptionsInstall$(var.Suffix)" Message="!(loc.WixSchedFirewallExceptionsInstall)" />
10 <ProgressText Action="$(var.Prefix)SchedFirewallExceptionsUninstall$(var.Suffix)" Message="!(loc.WixSchedFirewallExceptionsUninstall)" /> 10 <ProgressText Action="$(var.Prefix5)SchedFirewallExceptionsUninstall$(var.Suffix)" Message="!(loc.WixSchedFirewallExceptionsUninstall)" />
11 <ProgressText Action="$(var.Prefix)RollbackFirewallExceptionsInstall$(var.Suffix)" Message="!(loc.WixRollbackFirewallExceptionsInstall)" /> 11 <ProgressText Action="$(var.Prefix5)RollbackFirewallExceptionsInstall$(var.Suffix)" Message="!(loc.WixRollbackFirewallExceptionsInstall)" />
12 <ProgressText Action="$(var.Prefix)ExecFirewallExceptionsInstall$(var.Suffix)" Message="!(loc.WixExecFirewallExceptionsInstall)" /> 12 <ProgressText Action="$(var.Prefix5)ExecFirewallExceptionsInstall$(var.Suffix)" Message="!(loc.WixExecFirewallExceptionsInstall)" />
13 <ProgressText Action="$(var.Prefix)RollbackFirewallExceptionsUninstall$(var.Suffix)" Message="!(loc.WixRollbackFirewallExceptionsUninstall)" /> 13 <ProgressText Action="$(var.Prefix5)RollbackFirewallExceptionsUninstall$(var.Suffix)" Message="!(loc.WixRollbackFirewallExceptionsUninstall)" />
14 <ProgressText Action="$(var.Prefix)ExecFirewallExceptionsUninstall$(var.Suffix)" Message="!(loc.WixExecFirewallExceptionsUninstall)" /> 14 <ProgressText Action="$(var.Prefix5)ExecFirewallExceptionsUninstall$(var.Suffix)" Message="!(loc.WixExecFirewallExceptionsUninstall)" />
15 </UI> 15 </UI>
16 16
17 <CustomAction Id="$(var.Prefix)SchedFirewallExceptionsInstall$(var.Suffix)" DllEntry="SchedFirewallExceptionsInstall" Execute="immediate" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix)FWCA$(var.Suffix)" /> 17 <CustomAction Id="$(var.Prefix5)SchedFirewallExceptionsInstall$(var.Suffix)" DllEntry="SchedFirewallExceptionsInstall" Execute="immediate" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix5)FWCA$(var.Suffix)" />
18 <CustomAction Id="$(var.Prefix)SchedFirewallExceptionsUninstall$(var.Suffix)" DllEntry="SchedFirewallExceptionsUninstall" Execute="immediate" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix)FWCA$(var.Suffix)" /> 18 <CustomAction Id="$(var.Prefix5)SchedFirewallExceptionsUninstall$(var.Suffix)" DllEntry="SchedFirewallExceptionsUninstall" Execute="immediate" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix5)FWCA$(var.Suffix)" />
19 <CustomAction Id="$(var.Prefix)RollbackFirewallExceptionsInstall$(var.Suffix)" DllEntry="ExecFirewallExceptions" Execute="rollback" Impersonate="no" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix)FWCA$(var.Suffix)" /> 19 <CustomAction Id="$(var.Prefix5)RollbackFirewallExceptionsInstall$(var.Suffix)" DllEntry="ExecFirewallExceptions" Execute="rollback" Impersonate="no" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix5)FWCA$(var.Suffix)" />
20 <CustomAction Id="$(var.Prefix)ExecFirewallExceptionsInstall$(var.Suffix)" DllEntry="ExecFirewallExceptions" Execute="deferred" Impersonate="no" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix)FWCA$(var.Suffix)" /> 20 <CustomAction Id="$(var.Prefix5)ExecFirewallExceptionsInstall$(var.Suffix)" DllEntry="ExecFirewallExceptions" Execute="deferred" Impersonate="no" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix5)FWCA$(var.Suffix)" />
21 <CustomAction Id="$(var.Prefix)RollbackFirewallExceptionsUninstall$(var.Suffix)" DllEntry="ExecFirewallExceptions" Execute="rollback" Impersonate="no" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix)FWCA$(var.Suffix)" /> 21 <CustomAction Id="$(var.Prefix5)RollbackFirewallExceptionsUninstall$(var.Suffix)" DllEntry="ExecFirewallExceptions" Execute="rollback" Impersonate="no" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix5)FWCA$(var.Suffix)" />
22 <CustomAction Id="$(var.Prefix)ExecFirewallExceptionsUninstall$(var.Suffix)" DllEntry="ExecFirewallExceptions" Execute="deferred" Impersonate="no" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix)FWCA$(var.Suffix)" /> 22 <CustomAction Id="$(var.Prefix5)ExecFirewallExceptionsUninstall$(var.Suffix)" DllEntry="ExecFirewallExceptions" Execute="deferred" Impersonate="no" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix5)FWCA$(var.Suffix)" />
23 23
24 <!-- 24 <!--
25 We need the firewall on Windows XP SP2 or later. 25 We need the firewall on Windows Vista or later.
26 --> 26 -->
27 <InstallExecuteSequence> 27 <InstallExecuteSequence>
28 <Custom Action="$(var.Prefix)SchedFirewallExceptionsUninstall$(var.Suffix)" Before="RemoveFiles" Overridable="yes" Condition="VersionNT &gt;= 600 OR (VersionNT &gt;= 501 AND ((MsiNTProductType = 1 AND ServicePackLevel &gt;= 2) OR (MsiNTProductType &gt; 1 AND ServicePackLevel &gt;= 1)))" /> 28 <Custom Action="$(var.Prefix5)SchedFirewallExceptionsUninstall$(var.Suffix)" Before="RemoveFiles" Overridable="yes" Condition="VersionNT &gt;= 600" />
29 <Custom Action="$(var.Prefix)SchedFirewallExceptionsInstall$(var.Suffix)" After="InstallFiles" Overridable="yes" Condition="VersionNT &gt;= 600 OR (VersionNT &gt;= 501 AND ((MsiNTProductType = 1 AND ServicePackLevel &gt;= 2) OR (MsiNTProductType &gt; 1 AND ServicePackLevel &gt;= 1)))" /> 29 <Custom Action="$(var.Prefix5)SchedFirewallExceptionsInstall$(var.Suffix)" After="InstallFiles" Overridable="yes" Condition="VersionNT &gt;= 600" />
30 </InstallExecuteSequence> 30 </InstallExecuteSequence>
31 </Fragment> 31 </Fragment>
32 32
33 <!-- Firewall Custom Action DLL Definitions --> 33 <!-- Firewall Custom Action DLL Definitions -->
34 <Fragment> 34 <Fragment>
35 <Binary Id="$(var.Prefix)FWCA$(var.Suffix)" SourceFile="!(bindpath.$(var.platform))fwca.dll" /> 35 <Binary Id="$(var.Prefix5)FWCA$(var.Suffix)" SourceFile="!(bindpath.$(var.platform))fwca.dll" />
36 </Fragment> 36 </Fragment>
37</Include> 37</Include>
diff --git a/src/ext/caDecor.h b/src/ext/caDecor.h
index da274650..060032cf 100644
--- a/src/ext/caDecor.h
+++ b/src/ext/caDecor.h
@@ -11,3 +11,13 @@
11#else 11#else
12#define CUSTOM_ACTION_DECORATION(f) L"Wix4" f L"_X86" 12#define CUSTOM_ACTION_DECORATION(f) L"Wix4" f L"_X86"
13#endif 13#endif
14
15#if defined(_M_ARM64)
16#define CUSTOM_ACTION_DECORATION5(f) L"Wix5" f L"_A64"
17#elif defined(_M_AMD64)
18#define CUSTOM_ACTION_DECORATION5(f) L"Wix5" f L"_X64"
19#elif defined(_M_ARM)
20#define CUSTOM_ACTION_DECORATION5(f) L"Wix5" f L"_ARM"
21#else
22#define CUSTOM_ACTION_DECORATION5(f) L"Wix5" f L"_X86"
23#endif
diff --git a/src/ext/caDecor.wxi b/src/ext/caDecor.wxi
index b1711518..256d7586 100644
--- a/src/ext/caDecor.wxi
+++ b/src/ext/caDecor.wxi
@@ -8,6 +8,12 @@
8 8
9 <?define Prefix="Wix4" ?> 9 <?define Prefix="Wix4" ?>
10 10
11 <?ifdef Prefix5 ?>
12 <?undef Prefix5 ?>
13 <?endif?>
14
15 <?define Prefix5="Wix5" ?>
16
11 <?ifndef platform ?> 17 <?ifndef platform ?>
12 <?define platform="x86" ?> 18 <?define platform="x86" ?>
13 <?endif?> 19 <?endif?>
diff --git a/src/test/msi/TestData/FirewallExtensionTests/ProtocolRules/ProtocolRules.wixproj b/src/test/msi/TestData/FirewallExtensionTests/ProtocolRules/ProtocolRules.wixproj
new file mode 100644
index 00000000..b1770b0f
--- /dev/null
+++ b/src/test/msi/TestData/FirewallExtensionTests/ProtocolRules/ProtocolRules.wixproj
@@ -0,0 +1,13 @@
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<Project Sdk="WixToolset.Sdk">
3 <PropertyGroup>
4 <UpgradeCode>{4D188568-1CCF-4EEE-BC27-17C3DCC83E58}</UpgradeCode>
5 <ProductComponentsRef>true</ProductComponentsRef>
6 </PropertyGroup>
7 <ItemGroup>
8 <Compile Include="..\..\Templates\Product.wxs" Link="Product.wxs" />
9 </ItemGroup>
10 <ItemGroup>
11 <PackageReference Include="WixToolset.Firewall.wixext" />
12 </ItemGroup>
13</Project> \ No newline at end of file
diff --git a/src/test/msi/TestData/FirewallExtensionTests/ProtocolRules/product.wxs b/src/test/msi/TestData/FirewallExtensionTests/ProtocolRules/product.wxs
new file mode 100644
index 00000000..6a28ad0a
--- /dev/null
+++ b/src/test/msi/TestData/FirewallExtensionTests/ProtocolRules/product.wxs
@@ -0,0 +1,23 @@
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
3<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:fw="http://wixtoolset.org/schemas/v4/wxs/firewall">
4 <Fragment>
5 <ComponentGroup Id="ProductComponents">
6 <ComponentRef Id="FirewallComponent1"/>
7 </ComponentGroup>
8 </Fragment>
9
10 <Fragment>
11 <Component Id="FirewallComponent1" Guid="E465C8FE-5B81-4553-9CFC-E0CD96B9A36C" Directory="INSTALLFOLDER">
12 <fw:FirewallException Id="FirewallException09"
13 Description="WiX Toolset firewall exception rule integration test - protocol TCP"
14 Name="WiXToolset401 Test - 0009" Protocol="tcp" Port="900" Scope="any" />
15 <fw:FirewallException Id="FirewallException10"
16 Description="WiX Toolset firewall exception rule integration test - protocol UDP"
17 Name="WiXToolset401 Test - 0010" Protocol="udp" Port="1000" Scope="any" />
18 <fw:FirewallException Id="FirewallException11"
19 Description="WiX Toolset firewall exception rule integration test - ports can only be specified if protocol is TCP or UDP"
20 Name="WiXToolset401 Test - 0011" Protocol="134" Program="test.exe" Scope="any" />
21 </Component>
22 </Fragment>
23</Wix>
diff --git a/src/test/msi/TestData/FirewallExtensionTests/ScopeRules/ScopeRules.wixproj b/src/test/msi/TestData/FirewallExtensionTests/ScopeRules/ScopeRules.wixproj
new file mode 100644
index 00000000..b1770b0f
--- /dev/null
+++ b/src/test/msi/TestData/FirewallExtensionTests/ScopeRules/ScopeRules.wixproj
@@ -0,0 +1,13 @@
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<Project Sdk="WixToolset.Sdk">
3 <PropertyGroup>
4 <UpgradeCode>{4D188568-1CCF-4EEE-BC27-17C3DCC83E58}</UpgradeCode>
5 <ProductComponentsRef>true</ProductComponentsRef>
6 </PropertyGroup>
7 <ItemGroup>
8 <Compile Include="..\..\Templates\Product.wxs" Link="Product.wxs" />
9 </ItemGroup>
10 <ItemGroup>
11 <PackageReference Include="WixToolset.Firewall.wixext" />
12 </ItemGroup>
13</Project> \ No newline at end of file
diff --git a/src/test/msi/TestData/FirewallExtensionTests/ScopeRules/product.wxs b/src/test/msi/TestData/FirewallExtensionTests/ScopeRules/product.wxs
new file mode 100644
index 00000000..776c8675
--- /dev/null
+++ b/src/test/msi/TestData/FirewallExtensionTests/ScopeRules/product.wxs
@@ -0,0 +1,33 @@
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
3
4<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:fw="http://wixtoolset.org/schemas/v4/wxs/firewall">
5 <Fragment>
6 <ComponentGroup Id="ProductComponents">
7 <ComponentRef Id="FirewallComponent1"/>
8 </ComponentGroup>
9 </Fragment>
10
11 <Fragment>
12 <Component Id="FirewallComponent1" Guid="515AEDF0-A656-4006-8CE5-848ECCC680BD" Directory="INSTALLFOLDER">
13 <fw:FirewallException Id="FirewallException12"
14 Description="WiX Toolset firewall exception rule integration test - scope any"
15 Name="WiXToolset401 Test - 0012" Scope="any" Port="1200" />
16 <fw:FirewallException Id="FirewallException13"
17 Description="WiX Toolset firewall exception rule integration test - scope local subnet"
18 Name="WiXToolset401 Test - 0013" Scope="localSubnet" Port="1300" />
19 <fw:FirewallException Id="FirewallException14"
20 Description="WiX Toolset firewall exception rule integration test - scope DNS"
21 Name="WiXToolset401 Test - 0014" Scope="DNS" Port="1400" />
22 <fw:FirewallException Id="FirewallException15"
23 Description="WiX Toolset firewall exception rule integration test - scope DHCP"
24 Name="WiXToolset401 Test - 0015" Scope="DHCP" Port="1500" />
25 <fw:FirewallException Id="FirewallException16"
26 Description="WiX Toolset firewall exception rule integration test - scope WINS"
27 Name="WiXToolset401 Test - 0016" Scope="WINS" Port="1600" />
28 <fw:FirewallException Id="FirewallException17"
29 Description="WiX Toolset firewall exception rule integration test - scope default gateway"
30 Name="WiXToolset401 Test - 0017" Scope="defaultGateway" Port="1700" />
31 </Component>
32 </Fragment>
33</Wix>
diff --git a/src/test/msi/WixToolsetTest.MsiE2E/FirewallExtensionTests.cs b/src/test/msi/WixToolsetTest.MsiE2E/FirewallExtensionTests.cs
index 4106cd72..ce55aa14 100644
--- a/src/test/msi/WixToolsetTest.MsiE2E/FirewallExtensionTests.cs
+++ b/src/test/msi/WixToolsetTest.MsiE2E/FirewallExtensionTests.cs
@@ -315,5 +315,222 @@ namespace WixToolsetTest.MsiE2E
315 var log2 = product.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS, "NORULENAME=1"); 315 var log2 = product.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS, "NORULENAME=1");
316 Assert.True(LogVerifier.MessageInLogFile(log2, "failed to remove firewall rule")); 316 Assert.True(LogVerifier.MessageInLogFile(log2, "failed to remove firewall rule"));
317 } 317 }
318
319 [RuntimeFact]
320 public void VarietyOfProtocolValuesCanBeUsed()
321 {
322 var product = this.CreatePackageInstaller("ProtocolRules");
323 product.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
324
325 var expected1 = new RuleDetails("WiXToolset401 Test - 0009")
326 {
327 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
328 Description = "WiX Toolset firewall exception rule integration test - protocol TCP",
329 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
330 EdgeTraversal = false,
331 EdgeTraversalOptions = 0,
332 Enabled = true,
333 InterfaceTypes = "All",
334 LocalAddresses = "*",
335 Profiles = Int32.MaxValue,
336 Protocol = 6,
337 RemoteAddresses = "*",
338 SecureFlags = 0,
339 LocalPorts = "900",
340 RemotePorts = "*",
341 };
342
343 Verifier.VerifyFirewallRule("WiXToolset401 Test - 0009", expected1);
344
345
346 var expected2 = new RuleDetails("WiXToolset401 Test - 0010")
347 {
348 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
349 Description = "WiX Toolset firewall exception rule integration test - protocol UDP",
350 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
351 EdgeTraversal = false,
352 EdgeTraversalOptions = 0,
353 Enabled = true,
354 InterfaceTypes = "All",
355 LocalAddresses = "*",
356 Profiles = Int32.MaxValue,
357 Protocol = 17,
358 RemoteAddresses = "*",
359 SecureFlags = 0,
360 LocalPorts = "1000",
361 RemotePorts = "*",
362 };
363
364 Verifier.VerifyFirewallRule("WiXToolset401 Test - 0010", expected2);
365
366
367 var expected3 = new RuleDetails("WiXToolset401 Test - 0011")
368 {
369 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
370 ApplicationName = "test.exe",
371 Description = "WiX Toolset firewall exception rule integration test - ports can only be specified if protocol is TCP or UDP",
372 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
373 EdgeTraversal = true,
374 EdgeTraversalOptions = 1,
375 Enabled = true,
376 InterfaceTypes = "All",
377 LocalAddresses = "*",
378 Profiles = Int32.MaxValue,
379 Protocol = 134,
380 RemoteAddresses = "*",
381 SecureFlags = 0,
382 };
383
384 Verifier.VerifyFirewallRule("WiXToolset401 Test - 0011", expected3);
385
386 product.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
387
388 // verify the firewall exceptions have been removed.
389 Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0009"));
390 Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0010"));
391 Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0011"));
392 }
393
394 [RuntimeFact]
395 public void FullSetOfScopeValuesCanBeUsed()
396 {
397 var product = this.CreatePackageInstaller("ScopeRules");
398 product.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
399
400 var expected1 = new RuleDetails("WiXToolset401 Test - 0012")
401 {
402 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
403 Description = "WiX Toolset firewall exception rule integration test - scope any",
404 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
405 EdgeTraversal = false,
406 EdgeTraversalOptions = 0,
407 Enabled = true,
408 InterfaceTypes = "All",
409 LocalAddresses = "*",
410 Profiles = Int32.MaxValue,
411 Protocol = 6,
412 RemoteAddresses = "*",
413 SecureFlags = 0,
414 LocalPorts = "1200",
415 RemotePorts = "*",
416 };
417
418 Verifier.VerifyFirewallRule("WiXToolset401 Test - 0012", expected1);
419
420
421 var expected2 = new RuleDetails("WiXToolset401 Test - 0013")
422 {
423 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
424 Description = "WiX Toolset firewall exception rule integration test - scope local subnet",
425 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
426 EdgeTraversal = false,
427 EdgeTraversalOptions = 0,
428 Enabled = true,
429 InterfaceTypes = "All",
430 LocalAddresses = "*",
431 Profiles = Int32.MaxValue,
432 Protocol = 6,
433 RemoteAddresses = "LocalSubnet",
434 SecureFlags = 0,
435 LocalPorts = "1300",
436 RemotePorts = "*",
437 };
438
439 Verifier.VerifyFirewallRule("WiXToolset401 Test - 0013", expected2);
440
441
442 var expected3 = new RuleDetails("WiXToolset401 Test - 0014")
443 {
444 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
445 Description = "WiX Toolset firewall exception rule integration test - scope DNS",
446 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
447 EdgeTraversal = false,
448 EdgeTraversalOptions = 0,
449 Enabled = true,
450 InterfaceTypes = "All",
451 LocalAddresses = "*",
452 Profiles = Int32.MaxValue,
453 Protocol = 6,
454 RemoteAddresses = "DNS",
455 SecureFlags = 0,
456 LocalPorts = "1400",
457 RemotePorts = "*",
458 };
459
460 Verifier.VerifyFirewallRule("WiXToolset401 Test - 0014", expected3);
461
462
463 var expected4 = new RuleDetails("WiXToolset401 Test - 0015")
464 {
465 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
466 Description = "WiX Toolset firewall exception rule integration test - scope DHCP",
467 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
468 EdgeTraversal = false,
469 EdgeTraversalOptions = 0,
470 Enabled = true,
471 InterfaceTypes = "All",
472 LocalAddresses = "*",
473 Profiles = Int32.MaxValue,
474 Protocol = 6,
475 RemoteAddresses = "DHCP",
476 SecureFlags = 0,
477 LocalPorts = "1500",
478 RemotePorts = "*",
479 };
480
481 Verifier.VerifyFirewallRule("WiXToolset401 Test - 0015", expected4);
482
483
484 var expected5 = new RuleDetails("WiXToolset401 Test - 0016")
485 {
486 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
487 Description = "WiX Toolset firewall exception rule integration test - scope WINS",
488 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
489 EdgeTraversal = false,
490 EdgeTraversalOptions = 0,
491 Enabled = true,
492 InterfaceTypes = "All",
493 LocalAddresses = "*",
494 Profiles = Int32.MaxValue,
495 Protocol = 6,
496 RemoteAddresses = "WINS",
497 SecureFlags = 0,
498 LocalPorts = "1600",
499 RemotePorts = "*",
500 };
501
502 Verifier.VerifyFirewallRule("WiXToolset401 Test - 0016", expected5);
503
504
505 var expected6 = new RuleDetails("WiXToolset401 Test - 0017")
506 {
507 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
508 Description = "WiX Toolset firewall exception rule integration test - scope default gateway",
509 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
510 EdgeTraversal = false,
511 EdgeTraversalOptions = 0,
512 Enabled = true,
513 InterfaceTypes = "All",
514 LocalAddresses = "*",
515 Profiles = Int32.MaxValue,
516 Protocol = 6,
517 RemoteAddresses = "DefaultGateway",
518 SecureFlags = 0,
519 LocalPorts = "1700",
520 RemotePorts = "*",
521 };
522
523 Verifier.VerifyFirewallRule("WiXToolset401 Test - 0017", expected6);
524
525 product.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
526
527 // verify the firewall exceptions have been removed.
528 Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0012"));
529 Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0013"));
530 Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0014"));
531 Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0015"));
532 Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0016"));
533 Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0017"));
534 }
318 } 535 }
319} 536}
diff --git a/src/wix/WixToolset.Converters/WixConverter.cs b/src/wix/WixToolset.Converters/WixConverter.cs
index f3675ecc..178b90be 100644
--- a/src/wix/WixToolset.Converters/WixConverter.cs
+++ b/src/wix/WixToolset.Converters/WixConverter.cs
@@ -205,8 +205,8 @@ namespace WixToolset.Converters
205 { "WixDependencyRequire", "Wix4DependencyRequire_<PlatformSuffix>" }, 205 { "WixDependencyRequire", "Wix4DependencyRequire_<PlatformSuffix>" },
206 { "WixDependencyCheck", "Wix4DependencyCheck_<PlatformSuffix>" }, 206 { "WixDependencyCheck", "Wix4DependencyCheck_<PlatformSuffix>" },
207 { "WixQueryDirectXCaps", "Wix4QueryDirectXCaps_<PlatformSuffix>" }, 207 { "WixQueryDirectXCaps", "Wix4QueryDirectXCaps_<PlatformSuffix>" },
208 { "WixSchedFirewallExceptionsUninstall", "Wix4SchedFirewallExceptionsUninstall_<PlatformSuffix>" }, 208 { "WixSchedFirewallExceptionsUninstall", "Wix5SchedFirewallExceptionsUninstall_<PlatformSuffix>" },
209 { "WixSchedFirewallExceptionsInstall", "Wix4SchedFirewallExceptionsInstall_<PlatformSuffix>" }, 209 { "WixSchedFirewallExceptionsInstall", "Wix5SchedFirewallExceptionsInstall_<PlatformSuffix>" },
210 { "WixSchedHttpUrlReservationsUninstall", "Wix4SchedHttpUrlReservationsUninstall_<PlatformSuffix>" }, 210 { "WixSchedHttpUrlReservationsUninstall", "Wix4SchedHttpUrlReservationsUninstall_<PlatformSuffix>" },
211 { "WixSchedHttpUrlReservationsInstall", "Wix4SchedHttpUrlReservationsInstall_<PlatformSuffix>" }, 211 { "WixSchedHttpUrlReservationsInstall", "Wix4SchedHttpUrlReservationsInstall_<PlatformSuffix>" },
212 { "ConfigureIIs", "Wix4ConfigureIIs_<PlatformSuffix>" }, 212 { "ConfigureIIs", "Wix4ConfigureIIs_<PlatformSuffix>" },