aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorchris_bednarski <Chris.Bednarski@minfos.com.au>2023-09-21 16:03:28 +1000
committerBob Arnson <github@bobs.org>2023-11-19 12:17:13 -0500
commitdfb7512b85536b7726080648f2228cf8d0153724 (patch)
treed053018ee47afe7e349dda6739a6580c771a1a3d /src
parent80e604761b4f43b9b79a4878fcae360b071a7c35 (diff)
downloadwix-dfb7512b85536b7726080648f2228cf8d0153724.tar.gz
wix-dfb7512b85536b7726080648f2228cf8d0153724.tar.bz2
wix-dfb7512b85536b7726080648f2228cf8d0153724.zip
add firewall extension decompiler, make msi modifications work, add all attributes
Diffstat (limited to 'src')
-rw-r--r--src/ext/Firewall/ca/firewall.cpp980
-rw-r--r--src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs485
-rw-r--r--src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/PackageComponents.wxs39
-rw-r--r--src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingProperties/Package.en-us.wxl9
-rw-r--r--src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingProperties/Package.wxs15
-rw-r--r--src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingProperties/PackageComponents.wxs53
-rw-r--r--src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingProperties/example.txt1
-rw-r--r--src/ext/Firewall/test/WixToolsetTest.Firewall/WixToolsetTest.Firewall.csproj2
-rw-r--r--src/ext/Firewall/wixext/FirewallCompiler.cs623
-rw-r--r--src/ext/Firewall/wixext/FirewallConstants.cs17
-rw-r--r--src/ext/Firewall/wixext/FirewallDecompiler.cs317
-rw-r--r--src/ext/Firewall/wixext/FirewallErrors.cs29
-rw-r--r--src/ext/Firewall/wixext/FirewallTableDefinitions.cs28
-rw-r--r--src/ext/Firewall/wixext/Symbols/WixFirewallExceptionSymbol.cs142
-rw-r--r--src/ext/Firewall/wixext/WixToolset.Firewall.wixext.csproj4
-rw-r--r--src/ext/Util/wixext/UtilCompiler.cs13
-rw-r--r--src/internal/SetBuildNumber/Directory.Packages.props.pp1
-rw-r--r--src/test/burn/WixTestTools/Firewall/RuleDetails.cs8
-rw-r--r--src/test/msi/TestData/FirewallExtensionTests/CrossVersionMerge/CrossVersionMerge.wixproj13
-rw-r--r--src/test/msi/TestData/FirewallExtensionTests/CrossVersionMerge/Module401.msmbin0 -> 192512 bytes
-rw-r--r--src/test/msi/TestData/FirewallExtensionTests/CrossVersionMerge/package.wxs35
-rw-r--r--src/test/msi/TestData/FirewallExtensionTests/FirewallRulesInterfaces/FirewallRulesInterfaces.wixproj13
-rw-r--r--src/test/msi/TestData/FirewallExtensionTests/FirewallRulesInterfaces/product.wxs32
-rw-r--r--src/test/msi/TestData/FirewallExtensionTests/FirewallRulesProperties/FirewallRulesProperties.wixproj13
-rw-r--r--src/test/msi/TestData/FirewallExtensionTests/FirewallRulesProperties/product.wxs57
-rw-r--r--src/test/msi/TestData/FirewallExtensionTests/Module401/Module401.wixproj10
-rw-r--r--src/test/msi/TestData/FirewallExtensionTests/Module401/data/test.txt1
-rw-r--r--src/test/msi/TestData/FirewallExtensionTests/Module401/module.wxs36
-rw-r--r--src/test/msi/TestData/FirewallExtensionTests/ModuleCurrent/ModuleCurrent.wixproj10
-rw-r--r--src/test/msi/TestData/FirewallExtensionTests/ModuleCurrent/data/test.txt1
-rw-r--r--src/test/msi/TestData/FirewallExtensionTests/ModuleCurrent/module.wxs36
-rw-r--r--src/test/msi/TestData/FirewallExtensionTests/NestedService/NestedService.wixproj14
-rw-r--r--src/test/msi/TestData/FirewallExtensionTests/NestedService/product.wxs25
-rw-r--r--src/test/msi/WixToolsetTest.MsiE2E/FirewallExtensionTests.cs640
-rw-r--r--src/test/msi/WixToolsetTest.MsiE2E/WixToolsetTest.MsiE2E.csproj1
35 files changed, 3356 insertions, 347 deletions
diff --git a/src/ext/Firewall/ca/firewall.cpp b/src/ext/Firewall/ca/firewall.cpp
index eed6f9df..f50ae409 100644
--- a/src/ext/Firewall/ca/firewall.cpp
+++ b/src/ext/Firewall/ca/firewall.cpp
@@ -3,34 +3,54 @@
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 `Wix5FirewallException`"; 6L"SELECT `Name`, `RemoteAddresses`, `Port`, `Protocol`, `Program`, `Attributes`, `Profile`, `Component_`, `Description`, `Direction`, `Action`, `EdgeTraversal`, `Enabled`, `Grouping`, `IcmpTypesAndCodes`, `Interfaces`, `InterfaceTypes`, `LocalAddresses`, `RemotePort`, `ServiceName`, `LocalAppPackageId`, `LocalUserAuthorizedList`, `LocalUserOwner`, `RemoteMachineAuthorizedList`, `RemoteUserAuthorizedList`, `SecureFlags` 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, feqAction, feqEdgeTraversal, feqEnabled, feqGrouping, feqIcmpTypesAndCodes, feqInterfaces, feqInterfaceTypes, feqLocalAddresses, feqRemotePort, feqServiceName, feqLocalAppPackageId, feqLocalUserAuthorizedList, feqLocalUserOwner, feqRemoteMachineAuthorizedList, feqRemoteUserAuthorizedList, feqSecureFlags };
8enum eFirewallExceptionTarget { fetPort = 1, fetApplication, fetUnknown }; 8enum eFirewallExceptionAttributes { feaIgnoreFailures = 1, feaIgnoreUpdates = 2, feaEnableOnUpdate = 4, feaAddINetFwRule2 = 8, feaAddINetFwRule3 = 16 };
9enum eFirewallExceptionAttributes { feaIgnoreFailures = 1 };
10 9
11struct FIREWALL_EXCEPTION_ATTRIBUTES 10struct FIREWALL_EXCEPTION_ATTRIBUTES
12{ 11{
13 LPWSTR pwzName; 12 LPWSTR pwzName;
14
15 LPWSTR pwzRemoteAddresses;
16 LPWSTR pwzPort;
17 int iProtocol;
18 LPWSTR pwzProgram;
19 int iAttributes; 13 int iAttributes;
20 int iProfile; 14
15 // INetFwRule
16 int iAction;
17 LPWSTR pwzApplicationName;
21 LPWSTR pwzDescription; 18 LPWSTR pwzDescription;
22 int iDirection; 19 int iDirection;
20 int iEnabled;
21 LPWSTR pwzGrouping;
22 LPWSTR pwzIcmpTypesAndCodes;
23 LPWSTR pwzInterfaces;
24 LPWSTR pwzInterfaceTypes;
25 LPWSTR pwzLocalAddresses;
26 LPWSTR pwzLocalPorts;
27 int iProfile;
28 int iProtocol;
29 LPWSTR pwzRemoteAddresses;
30 LPWSTR pwzRemotePorts;
31 LPWSTR pwzServiceName;
32
33 // INetFwRule2
34 int iEdgeTraversal;
35
36 // INetFwRule3
37 LPWSTR pwzLocalAppPackageId;
38 LPWSTR pwzLocalUserAuthorizedList;
39 LPWSTR pwzLocalUserOwner;
40 LPWSTR pwzRemoteMachineAuthorizedList;
41 LPWSTR pwzRemoteUserAuthorizedList;
42 int iSecureFlags;
23}; 43};
24 44
25/****************************************************************** 45/******************************************************************
26 SchedFirewallExceptions - immediate custom action worker to 46 SchedFirewallExceptions - immediate custom action worker to
27 register and remove firewall exceptions. 47 register and remove firewall exceptions.
28 48
29********************************************************************/ 49********************************************************************/
30static UINT SchedFirewallExceptions( 50static UINT SchedFirewallExceptions(
31 __in MSIHANDLE hInstall, 51 __in MSIHANDLE hInstall,
32 WCA_TODO todoSched 52 __in WCA_TODO todoSched
33 ) 53)
34{ 54{
35 HRESULT hr = S_OK; 55 HRESULT hr = S_OK;
36 UINT er = ERROR_SUCCESS; 56 UINT er = ERROR_SUCCESS;
@@ -67,19 +87,19 @@ static UINT SchedFirewallExceptions(
67 hr = WcaGetRecordFormattedString(hRec, feqRemoteAddresses, &attrs.pwzRemoteAddresses); 87 hr = WcaGetRecordFormattedString(hRec, feqRemoteAddresses, &attrs.pwzRemoteAddresses);
68 ExitOnFailure(hr, "Failed to get firewall exception remote addresses."); 88 ExitOnFailure(hr, "Failed to get firewall exception remote addresses.");
69 89
70 hr = WcaGetRecordFormattedString(hRec, feqPort, &attrs.pwzPort); 90 hr = WcaGetRecordFormattedString(hRec, feqPort, &attrs.pwzLocalPorts);
71 ExitOnFailure(hr, "Failed to get firewall exception port."); 91 ExitOnFailure(hr, "Failed to get firewall exception port.");
72 92
73 hr = WcaGetRecordInteger(hRec, feqProtocol, &attrs.iProtocol); 93 hr = WcaGetRecordFormattedInteger(hRec, feqProtocol, &attrs.iProtocol);
74 ExitOnFailure(hr, "Failed to get firewall exception protocol."); 94 ExitOnFailure(hr, "Failed to get firewall exception protocol.");
75 95
76 hr = WcaGetRecordFormattedString(hRec, feqProgram, &attrs.pwzProgram); 96 hr = WcaGetRecordFormattedString(hRec, feqProgram, &attrs.pwzApplicationName);
77 ExitOnFailure(hr, "Failed to get firewall exception program."); 97 ExitOnFailure(hr, "Failed to get firewall exception program.");
78 98
79 hr = WcaGetRecordInteger(hRec, feqAttributes, &attrs.iAttributes); 99 hr = WcaGetRecordInteger(hRec, feqAttributes, &attrs.iAttributes);
80 ExitOnFailure(hr, "Failed to get firewall exception attributes."); 100 ExitOnFailure(hr, "Failed to get firewall exception attributes.");
81 101
82 hr = WcaGetRecordInteger(hRec, feqProfile, &attrs.iProfile); 102 hr = WcaGetRecordFormattedInteger(hRec, feqProfile, &attrs.iProfile);
83 ExitOnFailure(hr, "Failed to get firewall exception profile."); 103 ExitOnFailure(hr, "Failed to get firewall exception profile.");
84 104
85 hr = WcaGetRecordString(hRec, feqComponent, &pwzComponent); 105 hr = WcaGetRecordString(hRec, feqComponent, &pwzComponent);
@@ -91,6 +111,54 @@ static UINT SchedFirewallExceptions(
91 hr = WcaGetRecordInteger(hRec, feqDirection, &attrs.iDirection); 111 hr = WcaGetRecordInteger(hRec, feqDirection, &attrs.iDirection);
92 ExitOnFailure(hr, "Failed to get firewall exception direction."); 112 ExitOnFailure(hr, "Failed to get firewall exception direction.");
93 113
114 hr = WcaGetRecordFormattedInteger(hRec, feqAction, &attrs.iAction);
115 ExitOnFailure(hr, "Failed to get firewall exception action.");
116
117 hr = WcaGetRecordFormattedInteger(hRec, feqEdgeTraversal, &attrs.iEdgeTraversal);
118 ExitOnFailure(hr, "Failed to get firewall exception edge traversal.");
119
120 hr = WcaGetRecordFormattedInteger(hRec, feqEnabled, &attrs.iEnabled);
121 ExitOnFailure(hr, "Failed to get firewall exception enabled flag.");
122
123 hr = WcaGetRecordFormattedString(hRec, feqGrouping, &attrs.pwzGrouping);
124 ExitOnFailure(hr, "Failed to get firewall exception grouping.");
125
126 hr = WcaGetRecordFormattedString(hRec, feqIcmpTypesAndCodes, &attrs.pwzIcmpTypesAndCodes);
127 ExitOnFailure(hr, "Failed to get firewall exception ICMP types and codes.");
128
129 hr = WcaGetRecordFormattedString(hRec, feqInterfaces, &attrs.pwzInterfaces);
130 ExitOnFailure(hr, "Failed to get firewall exception interfaces.");
131
132 hr = WcaGetRecordFormattedString(hRec, feqInterfaceTypes, &attrs.pwzInterfaceTypes);
133 ExitOnFailure(hr, "Failed to get firewall exception interface types.");
134
135 hr = WcaGetRecordFormattedString(hRec, feqLocalAddresses, &attrs.pwzLocalAddresses);
136 ExitOnFailure(hr, "Failed to get firewall exception local addresses.");
137
138 hr = WcaGetRecordFormattedString(hRec, feqRemotePort, &attrs.pwzRemotePorts);
139 ExitOnFailure(hr, "Failed to get firewall exception remote port.");
140
141 hr = WcaGetRecordFormattedString(hRec, feqServiceName, &attrs.pwzServiceName);
142 ExitOnFailure(hr, "Failed to get firewall exception service name.");
143
144 hr = WcaGetRecordFormattedString(hRec, feqLocalAppPackageId, &attrs.pwzLocalAppPackageId);
145 ExitOnFailure(hr, "Failed to get firewall exception local app package id.");
146
147 hr = WcaGetRecordFormattedString(hRec, feqLocalUserAuthorizedList, &attrs.pwzLocalUserAuthorizedList);
148 ExitOnFailure(hr, "Failed to get firewall exception local user authorized list.");
149
150 hr = WcaGetRecordFormattedString(hRec, feqLocalUserOwner, &attrs.pwzLocalUserOwner);
151 ExitOnFailure(hr, "Failed to get firewall exception local user owner.");
152
153 hr = WcaGetRecordFormattedString(hRec, feqRemoteMachineAuthorizedList, &attrs.pwzRemoteMachineAuthorizedList);
154 ExitOnFailure(hr, "Failed to get firewall exception remote machine authorized list.");
155
156 hr = WcaGetRecordFormattedString(hRec, feqRemoteUserAuthorizedList, &attrs.pwzRemoteUserAuthorizedList);
157 ExitOnFailure(hr, "Failed to get firewall exception remote user authorized list.");
158
159 hr = WcaGetRecordFormattedInteger(hRec, feqSecureFlags, &attrs.iSecureFlags);
160 ExitOnFailure(hr, "Failed to get firewall exception secure flag.");
161
94 // figure out what we're doing for this exception, treating reinstall the same as install 162 // figure out what we're doing for this exception, treating reinstall the same as install
95 WCA_TODO todoComponent = WcaGetComponentToDo(pwzComponent); 163 WCA_TODO todoComponent = WcaGetComponentToDo(pwzComponent);
96 if ((WCA_TODO_REINSTALL == todoComponent ? WCA_TODO_INSTALL : todoComponent) != todoSched) 164 if ((WCA_TODO_REINSTALL == todoComponent ? WCA_TODO_INSTALL : todoComponent) != todoSched)
@@ -99,7 +167,6 @@ static UINT SchedFirewallExceptions(
99 continue; 167 continue;
100 } 168 }
101 169
102 // action :: name :: profile :: remoteaddresses :: attributes :: target :: {port::protocol | path}
103 ++cFirewallExceptions; 170 ++cFirewallExceptions;
104 hr = WcaWriteIntegerToCaData(todoComponent, &pwzCustomActionData); 171 hr = WcaWriteIntegerToCaData(todoComponent, &pwzCustomActionData);
105 ExitOnFailure(hr, "failed to write exception action to custom action data"); 172 ExitOnFailure(hr, "failed to write exception action to custom action data");
@@ -116,40 +183,75 @@ static UINT SchedFirewallExceptions(
116 hr = WcaWriteIntegerToCaData(attrs.iAttributes, &pwzCustomActionData); 183 hr = WcaWriteIntegerToCaData(attrs.iAttributes, &pwzCustomActionData);
117 ExitOnFailure(hr, "failed to write exception attributes to custom action data"); 184 ExitOnFailure(hr, "failed to write exception attributes to custom action data");
118 185
119 if (*attrs.pwzProgram) 186 hr = WcaWriteStringToCaData(attrs.pwzApplicationName, &pwzCustomActionData);
120 {
121 // If program is defined, we have an application exception.
122 hr = WcaWriteIntegerToCaData(fetApplication, &pwzCustomActionData);
123 ExitOnFailure(hr, "failed to write exception target (application) to custom action data");
124
125 hr = WcaWriteStringToCaData(attrs.pwzProgram, &pwzCustomActionData);
126 ExitOnFailure(hr, "failed to write application path to custom action data");
127 }
128 else
129 {
130 // we have a port-only exception
131 hr = WcaWriteIntegerToCaData(fetPort, &pwzCustomActionData);
132 ExitOnFailure(hr, "failed to write exception target (port) to custom action data");
133 }
134
135 hr = WcaWriteStringToCaData(attrs.pwzPort, &pwzCustomActionData);
136 ExitOnFailure(hr, "failed to write application path to custom action data"); 187 ExitOnFailure(hr, "failed to write application path to custom action data");
137 188
189 hr = WcaWriteStringToCaData(attrs.pwzLocalPorts, &pwzCustomActionData);
190 ExitOnFailure(hr, "failed to write local ports to custom action data");
191
138 hr = WcaWriteIntegerToCaData(attrs.iProtocol, &pwzCustomActionData); 192 hr = WcaWriteIntegerToCaData(attrs.iProtocol, &pwzCustomActionData);
139 ExitOnFailure(hr, "failed to write exception protocol to custom action data"); 193 ExitOnFailure(hr, "failed to write exception protocol to custom action data");
140 194
141 hr = WcaWriteStringToCaData(attrs.pwzDescription, &pwzCustomActionData); 195 hr = WcaWriteStringToCaData(attrs.pwzDescription, &pwzCustomActionData);
142 ExitOnFailure(hr, "failed to write firewall rule description to custom action data"); 196 ExitOnFailure(hr, "failed to write firewall exception description to custom action data");
143 197
144 hr = WcaWriteIntegerToCaData(attrs.iDirection, &pwzCustomActionData); 198 hr = WcaWriteIntegerToCaData(attrs.iDirection, &pwzCustomActionData);
145 ExitOnFailure(hr, "failed to write firewall rule direction to custom action data"); 199 ExitOnFailure(hr, "failed to write firewall exception direction to custom action data");
200
201 hr = WcaWriteIntegerToCaData(attrs.iAction, &pwzCustomActionData);
202 ExitOnFailure(hr, "failed to write exception action to custom action data");
203
204 hr = WcaWriteIntegerToCaData(attrs.iEdgeTraversal, &pwzCustomActionData);
205 ExitOnFailure(hr, "failed to write exception edge traversal to custom action data");
206
207 hr = WcaWriteIntegerToCaData(attrs.iEnabled, &pwzCustomActionData);
208 ExitOnFailure(hr, "failed to write exception enabled flag to custom action data");
209
210 hr = WcaWriteStringToCaData(attrs.pwzGrouping, &pwzCustomActionData);
211 ExitOnFailure(hr, "failed to write grouping to custom action data");
212
213 hr = WcaWriteStringToCaData(attrs.pwzIcmpTypesAndCodes, &pwzCustomActionData);
214 ExitOnFailure(hr, "failed to write icmp types and codes to custom action data");
215
216 hr = WcaWriteStringToCaData(attrs.pwzInterfaces, &pwzCustomActionData);
217 ExitOnFailure(hr, "failed to write interfaces to custom action data");
218
219 hr = WcaWriteStringToCaData(attrs.pwzInterfaceTypes, &pwzCustomActionData);
220 ExitOnFailure(hr, "failed to write interface types to custom action data");
221
222 hr = WcaWriteStringToCaData(attrs.pwzLocalAddresses, &pwzCustomActionData);
223 ExitOnFailure(hr, "failed to write local addresses to custom action data");
224
225 hr = WcaWriteStringToCaData(attrs.pwzRemotePorts, &pwzCustomActionData);
226 ExitOnFailure(hr, "failed to write remote ports to custom action data");
227
228 hr = WcaWriteStringToCaData(attrs.pwzServiceName, &pwzCustomActionData);
229 ExitOnFailure(hr, "failed to write service name to custom action data");
230
231 hr = WcaWriteStringToCaData(attrs.pwzLocalAppPackageId, &pwzCustomActionData);
232 ExitOnFailure(hr, "failed to write local app package id to custom action data");
233
234 hr = WcaWriteStringToCaData(attrs.pwzLocalUserAuthorizedList, &pwzCustomActionData);
235 ExitOnFailure(hr, "failed to write local user authorized list to custom action data");
236
237 hr = WcaWriteStringToCaData(attrs.pwzLocalUserOwner, &pwzCustomActionData);
238 ExitOnFailure(hr, "failed to write local user owner to custom action data");
239
240 hr = WcaWriteStringToCaData(attrs.pwzRemoteMachineAuthorizedList, &pwzCustomActionData);
241 ExitOnFailure(hr, "failed to write remote machine authorized list to custom action data");
242
243 hr = WcaWriteStringToCaData(attrs.pwzRemoteUserAuthorizedList, &pwzCustomActionData);
244 ExitOnFailure(hr, "failed to write remote user authorized list to custom action data");
245
246 hr = WcaWriteIntegerToCaData(attrs.iSecureFlags, &pwzCustomActionData);
247 ExitOnFailure(hr, "failed to write exception secure flags to custom action data");
146 } 248 }
147 249
148 // reaching the end of the list is actually a good thing, not an error 250 // reaching the end of the list is actually a good thing, not an error
149 if (E_NOMOREITEMS == hr) 251 if (E_NOMOREITEMS == hr)
150 { 252 {
151 hr = S_OK; 253 hr = S_OK;
152 } 254 }
153 ExitOnFailure(hr, "failure occured while processing Wix5FirewallException table"); 255 ExitOnFailure(hr, "failure occured while processing Wix5FirewallException table");
154 256
155 // schedule ExecFirewallExceptions if there's anything to do 257 // schedule ExecFirewallExceptions if there's anything to do
@@ -160,14 +262,14 @@ static UINT SchedFirewallExceptions(
160 if (WCA_TODO_INSTALL == todoSched) 262 if (WCA_TODO_INSTALL == todoSched)
161 { 263 {
162 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION5(L"RollbackFirewallExceptionsInstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION); 264 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION5(L"RollbackFirewallExceptionsInstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
163 ExitOnFailure(hr, "failed to schedule firewall install exceptions rollback"); 265 ExitOnFailure(hr, "failed to schedule firewall install exceptions rollback");
164 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION5(L"ExecFirewallExceptionsInstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION); 266 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION5(L"ExecFirewallExceptionsInstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
165 ExitOnFailure(hr, "failed to schedule firewall install exceptions execution"); 267 ExitOnFailure(hr, "failed to schedule firewall install exceptions execution");
166 } 268 }
167 else 269 else
168 { 270 {
169 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION5(L"RollbackFirewallExceptionsUninstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION); 271 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION5(L"RollbackFirewallExceptionsUninstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
170 ExitOnFailure(hr, "failed to schedule firewall uninstall exceptions rollback"); 272 ExitOnFailure(hr, "failed to schedule firewall uninstall exceptions rollback");
171 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION5(L"ExecFirewallExceptionsUninstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION); 273 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION5(L"ExecFirewallExceptionsUninstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
172 ExitOnFailure(hr, "failed to schedule firewall uninstall exceptions execution"); 274 ExitOnFailure(hr, "failed to schedule firewall uninstall exceptions execution");
173 } 275 }
@@ -180,53 +282,68 @@ static UINT SchedFirewallExceptions(
180LExit: 282LExit:
181 ReleaseStr(attrs.pwzName); 283 ReleaseStr(attrs.pwzName);
182 ReleaseStr(attrs.pwzRemoteAddresses); 284 ReleaseStr(attrs.pwzRemoteAddresses);
183 ReleaseStr(attrs.pwzPort); 285 ReleaseStr(attrs.pwzLocalPorts);
184 ReleaseStr(attrs.pwzProgram); 286 ReleaseStr(attrs.pwzApplicationName);
185 ReleaseStr(attrs.pwzDescription); 287 ReleaseStr(attrs.pwzDescription);
288 ReleaseStr(attrs.pwzGrouping);
289 ReleaseStr(attrs.pwzIcmpTypesAndCodes);
290 ReleaseStr(attrs.pwzInterfaces);
291 ReleaseStr(attrs.pwzInterfaceTypes);
292 ReleaseStr(attrs.pwzLocalAddresses);
293 ReleaseStr(attrs.pwzRemotePorts);
294 ReleaseStr(attrs.pwzServiceName);
295 ReleaseStr(attrs.pwzLocalAppPackageId);
296 ReleaseStr(attrs.pwzLocalUserAuthorizedList);
297 ReleaseStr(attrs.pwzLocalUserOwner);
298 ReleaseStr(attrs.pwzRemoteMachineAuthorizedList);
299 ReleaseStr(attrs.pwzRemoteUserAuthorizedList);
186 ReleaseStr(pwzComponent); 300 ReleaseStr(pwzComponent);
187 ReleaseStr(pwzCustomActionData); 301 ReleaseStr(pwzCustomActionData);
188 302
189 return WcaFinalize(er = FAILED(hr) ? ERROR_INSTALL_FAILURE : er); 303 return WcaFinalize(er = FAILED(hr) ? ERROR_INSTALL_FAILURE : er);
190} 304}
191 305
192/****************************************************************** 306
307/*******************************************************************
193 SchedFirewallExceptionsInstall - immediate custom action entry 308 SchedFirewallExceptionsInstall - immediate custom action entry
194 point to register firewall exceptions. 309 point to register firewall exceptions.
195 310
196********************************************************************/ 311********************************************************************/
197extern "C" UINT __stdcall SchedFirewallExceptionsInstall( 312extern "C" UINT __stdcall SchedFirewallExceptionsInstall(
198 __in MSIHANDLE hInstall 313 __in MSIHANDLE hInstall
199 ) 314)
200{ 315{
201 return SchedFirewallExceptions(hInstall, WCA_TODO_INSTALL); 316 return SchedFirewallExceptions(hInstall, WCA_TODO_INSTALL);
202} 317}
203 318
204/****************************************************************** 319
320/*******************************************************************
205 SchedFirewallExceptionsUninstall - immediate custom action entry 321 SchedFirewallExceptionsUninstall - immediate custom action entry
206 point to remove firewall exceptions. 322 point to remove firewall exceptions.
207 323
208********************************************************************/ 324********************************************************************/
209extern "C" UINT __stdcall SchedFirewallExceptionsUninstall( 325extern "C" UINT __stdcall SchedFirewallExceptionsUninstall(
210 __in MSIHANDLE hInstall 326 __in MSIHANDLE hInstall
211 ) 327)
212{ 328{
213 return SchedFirewallExceptions(hInstall, WCA_TODO_UNINSTALL); 329 return SchedFirewallExceptions(hInstall, WCA_TODO_UNINSTALL);
214} 330}
215 331
216/****************************************************************** 332
333/*******************************************************************
217 GetFirewallRules - Get the collection of firewall rules. 334 GetFirewallRules - Get the collection of firewall rules.
218 335
219********************************************************************/ 336********************************************************************/
220static HRESULT GetFirewallRules( 337static HRESULT GetFirewallRules(
221 __in BOOL fIgnoreFailures, 338 __in BOOL fIgnoreFailures,
222 __out INetFwRules** ppNetFwRules 339 __out INetFwRules** ppNetFwRules
223 ) 340)
224{ 341{
225 HRESULT hr = S_OK; 342 HRESULT hr = S_OK;
226 INetFwPolicy2* pNetFwPolicy2 = NULL; 343 INetFwPolicy2* pNetFwPolicy2 = NULL;
227 INetFwRules* pNetFwRules = NULL; 344 INetFwRules* pNetFwRules = NULL;
228 *ppNetFwRules = NULL; 345 *ppNetFwRules = NULL;
229 346
230 do 347 do
231 { 348 {
232 ReleaseNullObject(pNetFwPolicy2); 349 ReleaseNullObject(pNetFwPolicy2);
@@ -262,7 +379,7 @@ static HRESULT GetFirewallRules(
262 379
263 *ppNetFwRules = pNetFwRules; 380 *ppNetFwRules = pNetFwRules;
264 pNetFwRules = NULL; 381 pNetFwRules = NULL;
265 382
266LExit: 383LExit:
267 ReleaseObject(pNetFwPolicy2); 384 ReleaseObject(pNetFwPolicy2);
268 ReleaseObject(pNetFwRules); 385 ReleaseObject(pNetFwRules);
@@ -270,51 +387,380 @@ LExit:
270 return hr; 387 return hr;
271} 388}
272 389
273/****************************************************************** 390
274 CreateFwRuleObject - CoCreate a firewall rule, and set the common set of properties which are shared 391/*******************************************************************
275 between port and application firewall rules 392 CreateFwRuleObject - CoCreate a firewall rule, and set the name
276 393
277********************************************************************/ 394********************************************************************/
278static HRESULT CreateFwRuleObject( 395static HRESULT CreateFwRuleObject(
279 __in BSTR bstrName, 396 __in BSTR bstrName,
280 __in FIREWALL_EXCEPTION_ATTRIBUTES const& attrs,
281 __out INetFwRule** ppNetFwRule 397 __out INetFwRule** ppNetFwRule
282 ) 398)
399{
400 HRESULT hr = S_OK;
401 INetFwRule* pNetFwRule = NULL;
402 *ppNetFwRule = NULL;
403
404 hr = ::CoCreateInstance(__uuidof(NetFwRule), NULL, CLSCTX_ALL, __uuidof(INetFwRule), (LPVOID*)&pNetFwRule);
405 ExitOnFailure(hr, "failed to create NetFwRule object");
406
407 hr = pNetFwRule->put_Name(bstrName);
408 ExitOnFailure(hr, "failed to set firewall exception name");
409
410 *ppNetFwRule = pNetFwRule;
411
412LExit:
413 return hr;
414}
415
416
417/*********************************************************************
418 GetFwRuleInterfaces - pack firewall rule interfaces into a VARIANT.
419 The populated VARIANT needs to be cleaned up by the calling function.
420
421**********************************************************************/
422static HRESULT GetFwRuleInterfaces(
423 __in FIREWALL_EXCEPTION_ATTRIBUTES const& attrs,
424 __out VARIANT& vInterfaces
425)
426{
427 HRESULT hr = S_OK;
428 BSTR bstrInterfaces = NULL;
429 const WCHAR FORBIDDEN_FIREWALL_CHAR = L'|';
430 LONG iInterfacesCount = 0;
431 UINT iLength = 0;
432 LONG iIndex = 0;
433
434 ::VariantInit(&vInterfaces);
435 ExitOnNull(attrs.pwzInterfaces, hr, S_OK, "No interfaces to pack");
436
437 bstrInterfaces = ::SysAllocString(attrs.pwzInterfaces);
438 ExitOnNull(bstrInterfaces, hr, E_OUTOFMEMORY, "failed SysAllocString for interfaces");
439
440 iLength = ::SysStringLen(bstrInterfaces);
441
442 LPWSTR pwzT = bstrInterfaces;
443 while (*pwzT)
444 {
445 if (FORBIDDEN_FIREWALL_CHAR == *pwzT)
446 {
447 *pwzT = L'\0';
448 pwzT++;
449
450 // skip empty values inside the interfaces eg. |||
451 if (*pwzT && FORBIDDEN_FIREWALL_CHAR != *pwzT)
452 {
453 iInterfacesCount++;
454 }
455 }
456 else
457 {
458 if (pwzT == bstrInterfaces)
459 {
460 iInterfacesCount++;
461 }
462
463 pwzT++;
464 }
465 }
466
467 ExitOnNull(iInterfacesCount, hr, S_OK, "All interfaces are empty values");
468
469 vInterfaces.vt = VT_ARRAY | VT_VARIANT;
470 // this will be cleaned up by ReleaseVariant call of the calling function
471 vInterfaces.parray = SafeArrayCreateVector(VT_VARIANT, 0, iInterfacesCount);
472
473 for (LPCWSTR pwzElement = bstrInterfaces; pwzElement < (bstrInterfaces + iLength); ++pwzElement)
474 {
475 if (*pwzElement)
476 {
477 VARIANT vElement;
478 ::VariantInit(&vElement);
479
480 vElement.vt = VT_BSTR;
481 // this will be cleaned up by ReleaseVariant call of the calling function
482 vElement.bstrVal = ::SysAllocString(pwzElement);
483 ExitOnNull(vElement.bstrVal, hr, E_OUTOFMEMORY, "failed SysAllocString for interface element");
484
485 hr = SafeArrayPutElement(vInterfaces.parray, &iIndex, &vElement);
486 ExitOnFailure(hr, "failed to put interface '%ls' into safe array", pwzElement);
487
488 pwzElement += ::SysStringLen(vElement.bstrVal);
489 iIndex++;
490 }
491 }
492
493LExit:
494 ReleaseBSTR(bstrInterfaces);
495
496 return hr;
497}
498
499/******************************************************************************
500 UpdateFwRule2Object - update properties for a firewall INetFwRule2 interface.
501 Requires Windows 7 / 2008 R2
502
503 ******************************************************************************/
504static HRESULT UpdateFwRule2Object(
505 __in INetFwRule* pNetFwRule,
506 __in BOOL fUpdateRule,
507 __in FIREWALL_EXCEPTION_ATTRIBUTES const& attrs
508)
283{ 509{
284 HRESULT hr = S_OK; 510 HRESULT hr = S_OK;
511 INetFwRule2* pNetFwRule2 = NULL;
512
513 hr = pNetFwRule->QueryInterface(__uuidof(INetFwRule2), (LPVOID*)&pNetFwRule2);
514 ExitOnFailure(hr, "failed to query INetFwRule2 interface");
515
516 if (MSI_NULL_INTEGER != attrs.iEdgeTraversal)
517 {
518 hr = pNetFwRule2->put_EdgeTraversalOptions(attrs.iEdgeTraversal);
519 ExitOnFailure(hr, "failed to set exception edge traversal option");
520 }
521 else if (fUpdateRule)
522 {
523 hr = pNetFwRule2->put_EdgeTraversalOptions(NET_FW_EDGE_TRAVERSAL_TYPE_DENY);
524 ExitOnFailure(hr, "failed to remove exception edge traversal option");
525 }
526
527LExit:
528 ReleaseObject(pNetFwRule2);
529
530 return hr;
531}
532
533
534/******************************************************************************
535 UpdateFwRule3Object - update properties for a firewall INetFwRule3 interface.
536 Requires Windows 8 / 2012
537
538 ******************************************************************************/
539static HRESULT UpdateFwRule3Object(
540 __in INetFwRule* pNetFwRule,
541 __in BOOL fUpdateRule,
542 __in FIREWALL_EXCEPTION_ATTRIBUTES const& attrs
543)
544{
545 HRESULT hr = S_OK;
546
547 BSTR bstrLocalAppPackageId = NULL;
548 BSTR bstrLocalUserAuthorizedList = NULL;
549 BSTR bstrLocalUserOwner = NULL;
550 BSTR bstrRemoteMachineAuthorizedList = NULL;
551 BSTR bstrRemoteUserAuthorizedList = NULL;
552 INetFwRule3* pNetFwRule3 = NULL;
553
554 bstrLocalAppPackageId = ::SysAllocString(attrs.pwzLocalAppPackageId);
555 ExitOnNull(bstrLocalAppPackageId, hr, E_OUTOFMEMORY, "failed SysAllocString for local app package id");
556 bstrLocalUserAuthorizedList = ::SysAllocString(attrs.pwzLocalUserAuthorizedList);
557 ExitOnNull(bstrLocalUserAuthorizedList, hr, E_OUTOFMEMORY, "failed SysAllocString for local user authorized list");
558 bstrLocalUserOwner = ::SysAllocString(attrs.pwzLocalUserOwner);
559 ExitOnNull(bstrLocalUserOwner, hr, E_OUTOFMEMORY, "failed SysAllocString for local user owner");
560 bstrRemoteMachineAuthorizedList = ::SysAllocString(attrs.pwzRemoteMachineAuthorizedList);
561 ExitOnNull(bstrRemoteMachineAuthorizedList, hr, E_OUTOFMEMORY, "failed SysAllocString for remote machine authorized list");
562 bstrRemoteUserAuthorizedList = ::SysAllocString(attrs.pwzRemoteUserAuthorizedList);
563 ExitOnNull(bstrRemoteUserAuthorizedList, hr, E_OUTOFMEMORY, "failed SysAllocString for remote user authorized list");
564
565 hr = pNetFwRule->QueryInterface(__uuidof(INetFwRule3), (LPVOID*)&pNetFwRule3);
566 ExitOnFailure(hr, "failed to query INetFwRule3 interface");
567
568 if (bstrLocalAppPackageId && *bstrLocalAppPackageId)
569 {
570 hr = pNetFwRule3->put_LocalAppPackageId(bstrLocalAppPackageId);
571 ExitOnFailure(hr, "failed to set exception local app package id");
572 }
573 else if (fUpdateRule)
574 {
575 hr = pNetFwRule3->put_LocalAppPackageId(NULL);
576 ExitOnFailure(hr, "failed to remove exception local app package id");
577 }
578
579 if (bstrLocalUserAuthorizedList && *bstrLocalUserAuthorizedList)
580 {
581 hr = pNetFwRule3->put_LocalUserAuthorizedList(bstrLocalUserAuthorizedList);
582 ExitOnFailure(hr, "failed to set exception local user authorized list");
583 }
584 else if (fUpdateRule)
585 {
586 hr = pNetFwRule3->put_LocalUserAuthorizedList(NULL);
587 ExitOnFailure(hr, "failed to remove exception local user authorized list");
588 }
589
590 if (bstrLocalUserOwner && *bstrLocalUserOwner)
591 {
592 hr = pNetFwRule3->put_LocalUserOwner(bstrLocalUserOwner);
593 ExitOnFailure(hr, "failed to set exception local user owner");
594 }
595 else if (fUpdateRule)
596 {
597 hr = pNetFwRule3->put_LocalUserOwner(NULL);
598 ExitOnFailure(hr, "failed to remove exception local user owner");
599 }
600
601 if (bstrRemoteMachineAuthorizedList && *bstrRemoteMachineAuthorizedList)
602 {
603 hr = pNetFwRule3->put_RemoteMachineAuthorizedList(bstrRemoteMachineAuthorizedList);
604 ExitOnFailure(hr, "failed to set exception remote machine authorized list");
605 }
606 else if (fUpdateRule)
607 {
608 hr = pNetFwRule3->put_RemoteMachineAuthorizedList(NULL);
609 ExitOnFailure(hr, "failed to remove exception remote machine authorized list");
610 }
611
612 if (bstrRemoteUserAuthorizedList && *bstrRemoteUserAuthorizedList)
613 {
614 hr = pNetFwRule3->put_RemoteUserAuthorizedList(bstrRemoteUserAuthorizedList);
615 ExitOnFailure(hr, "failed to set exception remote user authorized list");
616 }
617 else if (fUpdateRule)
618 {
619 hr = pNetFwRule3->put_RemoteUserAuthorizedList(NULL);
620 ExitOnFailure(hr, "failed to remove exception remote user authorized list");
621 }
622
623 if (MSI_NULL_INTEGER != attrs.iSecureFlags)
624 {
625 hr = pNetFwRule3->put_SecureFlags(attrs.iSecureFlags);
626 ExitOnFailure(hr, "failed to set exception IPsec secure flags");
627 }
628 else if (fUpdateRule)
629 {
630 hr = pNetFwRule3->put_SecureFlags(NET_FW_AUTHENTICATE_NONE);
631 ExitOnFailure(hr, "failed to reset exception IPsec secure flags");
632 }
633
634LExit:
635 ReleaseBSTR(bstrLocalAppPackageId);
636 ReleaseBSTR(bstrLocalUserAuthorizedList);
637 ReleaseBSTR(bstrLocalUserOwner);
638 ReleaseBSTR(bstrRemoteMachineAuthorizedList);
639 ReleaseBSTR(bstrRemoteUserAuthorizedList);
640 ReleaseObject(pNetFwRule3);
641
642 return hr;
643}
644
645
646/**********************************************************************
647 UpdateFwRuleObject - update all properties for a basic firewall rule.
648 Requires Windows Vista / 2008
649
650 **********************************************************************/
651static HRESULT UpdateFwRuleObject(
652 __in INetFwRule* pNetFwRule,
653 __in BOOL fUpdateRule,
654 __in FIREWALL_EXCEPTION_ATTRIBUTES const& attrs
655)
656{
657 HRESULT hr = S_OK;
658 BSTR bstrEmpty = NULL;
285 BSTR bstrRemoteAddresses = NULL; 659 BSTR bstrRemoteAddresses = NULL;
660 BSTR bstrFile = NULL;
286 BSTR bstrPort = NULL; 661 BSTR bstrPort = NULL;
287 BSTR bstrDescription = NULL; 662 BSTR bstrDescription = NULL;
288 INetFwRule* pNetFwRule = NULL; 663 BSTR bstrGrouping = NULL;
289 *ppNetFwRule = NULL; 664 BSTR bstrIcmpTypesAndCodes = NULL;
665 BSTR bstrInterfaceTypes = NULL;
666 BSTR bstrLocalAddresses = NULL;
667 BSTR bstrRemotePort = NULL;
668 BSTR bstrServiceName = NULL;
669 VARIANT vInterfaces;
670 ::VariantInit(&vInterfaces);
671 LONG iProtocol = 0;
672
673 INetFwRule2* pNetFwRule2 = NULL;
290 674
291 // convert to BSTRs to make COM happy 675 // convert to BSTRs to make COM happy
676 bstrEmpty = ::SysAllocString(L"");
677 ExitOnNull(bstrEmpty, hr, E_OUTOFMEMORY, "failed SysAllocString for empty placeholder");
678
292 bstrRemoteAddresses = ::SysAllocString(attrs.pwzRemoteAddresses); 679 bstrRemoteAddresses = ::SysAllocString(attrs.pwzRemoteAddresses);
293 ExitOnNull(bstrRemoteAddresses, hr, E_OUTOFMEMORY, "failed SysAllocString for remote addresses"); 680 ExitOnNull(bstrRemoteAddresses, hr, E_OUTOFMEMORY, "failed SysAllocString for remote addresses");
294 bstrPort = ::SysAllocString(attrs.pwzPort); 681 bstrFile = ::SysAllocString(attrs.pwzApplicationName);
682 ExitOnNull(bstrFile, hr, E_OUTOFMEMORY, "failed SysAllocString for application name");
683 bstrPort = ::SysAllocString(attrs.pwzLocalPorts);
295 ExitOnNull(bstrPort, hr, E_OUTOFMEMORY, "failed SysAllocString for port"); 684 ExitOnNull(bstrPort, hr, E_OUTOFMEMORY, "failed SysAllocString for port");
296 bstrDescription = ::SysAllocString(attrs.pwzDescription); 685 bstrDescription = ::SysAllocString(attrs.pwzDescription);
297 ExitOnNull(bstrDescription, hr, E_OUTOFMEMORY, "failed SysAllocString for description"); 686 ExitOnNull(bstrDescription, hr, E_OUTOFMEMORY, "failed SysAllocString for description");
687 bstrGrouping = ::SysAllocString(attrs.pwzGrouping);
688 ExitOnNull(bstrGrouping, hr, E_OUTOFMEMORY, "failed SysAllocString for grouping");
689 bstrIcmpTypesAndCodes = ::SysAllocString(attrs.pwzIcmpTypesAndCodes);
690 ExitOnNull(bstrIcmpTypesAndCodes, hr, E_OUTOFMEMORY, "failed SysAllocString for icmp types and codes");
691 bstrInterfaceTypes = ::SysAllocString(attrs.pwzInterfaceTypes);
692 ExitOnNull(bstrInterfaceTypes, hr, E_OUTOFMEMORY, "failed SysAllocString for interface types");
693 bstrLocalAddresses = ::SysAllocString(attrs.pwzLocalAddresses);
694 ExitOnNull(bstrLocalAddresses, hr, E_OUTOFMEMORY, "failed SysAllocString for local addresses");
695 bstrRemotePort = ::SysAllocString(attrs.pwzRemotePorts);
696 ExitOnNull(bstrRemotePort, hr, E_OUTOFMEMORY, "failed SysAllocString for remote port");
697 bstrServiceName = ::SysAllocString(attrs.pwzServiceName);
698 ExitOnNull(bstrServiceName, hr, E_OUTOFMEMORY, "failed SysAllocString for service name");
699
700 if (fUpdateRule)
701 {
702 hr = pNetFwRule->get_Protocol(&iProtocol);
703 ExitOnFailure(hr, "failed to get exception protocol");
298 704
299 hr = ::CoCreateInstance(__uuidof(NetFwRule), NULL, CLSCTX_ALL, __uuidof(INetFwRule), (void**)&pNetFwRule); 705 // If you are editing a TCP port rule and converting it into an ICMP rule,
300 ExitOnFailure(hr, "failed to create NetFwRule object"); 706 // first delete the ports, change protocol from TCP to ICMP, and then add the ports.
301 707
302 hr = pNetFwRule->put_Name(bstrName); 708 switch (iProtocol)
303 ExitOnFailure(hr, "failed to set exception name"); 709 {
710 case NET_FW_IP_PROTOCOL_ANY:
711 break;
304 712
305 hr = pNetFwRule->put_Profiles(static_cast<NET_FW_PROFILE_TYPE2>(attrs.iProfile)); 713 case 1: // ICMP
306 ExitOnFailure(hr, "failed to set exception profile"); 714 hr = pNetFwRule->put_IcmpTypesAndCodes(NULL);
715 ExitOnFailure(hr, "failed to remove exception icmp types and codes");
716 // fall through and reset ports too
307 717
718 default:
719 hr = pNetFwRule->put_LocalPorts(NULL);
720 ExitOnFailure(hr, "failed to update exception local ports to NULL");
721
722 hr = pNetFwRule->put_RemotePorts(NULL);
723 ExitOnFailure(hr, "failed to update exception remote ports to NULL");
724 break;
725 }
726 }
727
728 if (MSI_NULL_INTEGER != attrs.iProfile)
729 {
730 hr = pNetFwRule->put_Profiles(static_cast<NET_FW_PROFILE_TYPE2> (attrs.iProfile));
731 ExitOnFailure(hr, "failed to set exception profile");
732 }
733 else if (fUpdateRule)
734 {
735 hr = pNetFwRule->put_Profiles(NET_FW_PROFILE2_ALL);
736 ExitOnFailure(hr, "failed to reset exception profile to all");
737 }
738
739 // The Protocol property must be set before the LocalPorts/RemotePorts properties or an error will be returned.
308 if (MSI_NULL_INTEGER != attrs.iProtocol) 740 if (MSI_NULL_INTEGER != attrs.iProtocol)
309 { 741 {
310 hr = pNetFwRule->put_Protocol(static_cast<NET_FW_IP_PROTOCOL>(attrs.iProtocol)); 742 hr = pNetFwRule->put_Protocol(static_cast<NET_FW_IP_PROTOCOL> (attrs.iProtocol));
311 ExitOnFailure(hr, "failed to set exception protocol"); 743 ExitOnFailure(hr, "failed to set exception protocol");
312 } 744 }
745 else if (fUpdateRule)
746 {
747 if ((bstrPort && *bstrPort) || (bstrRemotePort && *bstrRemotePort))
748 {
749 // default protocol is "TCP" in the WiX firewall compiler if a port is specified
750 hr = pNetFwRule->put_Protocol(NET_FW_IP_PROTOCOL_TCP);
751 ExitOnFailure(hr, "failed to reset exception protocol to TCP");
752 }
753 else
754 {
755 hr = pNetFwRule->put_Protocol(NET_FW_IP_PROTOCOL_ANY);
756 ExitOnFailure(hr, "failed to reset exception protocol to ANY");
757 }
758 }
313 759
314 if (bstrPort && *bstrPort) 760 if (bstrPort && *bstrPort)
315 { 761 {
316 hr = pNetFwRule->put_LocalPorts(bstrPort); 762 hr = pNetFwRule->put_LocalPorts(bstrPort);
317 ExitOnFailure(hr, "failed to set exception port"); 763 ExitOnFailure(hr, "failed to set exception local ports '%ls'", bstrPort);
318 } 764 }
319 765
320 if (bstrRemoteAddresses && *bstrRemoteAddresses) 766 if (bstrRemoteAddresses && *bstrRemoteAddresses)
@@ -322,122 +768,195 @@ static HRESULT CreateFwRuleObject(
322 hr = pNetFwRule->put_RemoteAddresses(bstrRemoteAddresses); 768 hr = pNetFwRule->put_RemoteAddresses(bstrRemoteAddresses);
323 ExitOnFailure(hr, "failed to set exception remote addresses '%ls'", bstrRemoteAddresses); 769 ExitOnFailure(hr, "failed to set exception remote addresses '%ls'", bstrRemoteAddresses);
324 } 770 }
771 else if (fUpdateRule)
772 {
773 hr = pNetFwRule->put_RemoteAddresses(bstrEmpty);
774 ExitOnFailure(hr, "failed to remove exception remote addresses");
775 }
325 776
326 if (bstrDescription && *bstrDescription) 777 if (bstrDescription && *bstrDescription)
327 { 778 {
328 hr = pNetFwRule->put_Description(bstrDescription); 779 hr = pNetFwRule->put_Description(bstrDescription);
329 ExitOnFailure(hr, "failed to set exception description '%ls'", bstrDescription); 780 ExitOnFailure(hr, "failed to set exception description '%ls'", bstrDescription);
330 } 781 }
782 else if (fUpdateRule)
783 {
784 hr = pNetFwRule->put_Description(bstrEmpty);
785 ExitOnFailure(hr, "failed to remove exception description");
786 }
331 787
332 if (MSI_NULL_INTEGER != attrs.iDirection) 788 if (MSI_NULL_INTEGER != attrs.iDirection)
333 { 789 {
334 hr = pNetFwRule->put_Direction(static_cast<NET_FW_RULE_DIRECTION> (attrs.iDirection)); 790 hr = pNetFwRule->put_Direction(static_cast<NET_FW_RULE_DIRECTION> (attrs.iDirection));
335 ExitOnFailure(hr, "failed to set exception direction"); 791 ExitOnFailure(hr, "failed to set exception direction");
336 } 792 }
793 else if (fUpdateRule)
794 {
795 hr = pNetFwRule->put_Direction(NET_FW_RULE_DIR_IN);
796 ExitOnFailure(hr, "failed to reset exception direction to in");
797 }
337 798
338 *ppNetFwRule = pNetFwRule; 799 if (MSI_NULL_INTEGER != attrs.iAction)
339 pNetFwRule = NULL; 800 {
801 hr = pNetFwRule->put_Action(static_cast<NET_FW_ACTION> (attrs.iAction));
802 ExitOnFailure(hr, "failed to set exception action");
803 }
804 else if (fUpdateRule)
805 {
806 hr = pNetFwRule->put_Action(NET_FW_ACTION_ALLOW);
807 ExitOnFailure(hr, "failed to reset exception action to allow");
808 }
340 809
341LExit: 810 if (bstrFile && *bstrFile)
342 ReleaseBSTR(bstrRemoteAddresses); 811 {
343 ReleaseBSTR(bstrPort); 812 hr = pNetFwRule->put_ApplicationName(bstrFile);
344 ReleaseBSTR(bstrDescription); 813 ExitOnFailure(hr, "failed to set exception application name");
345 ReleaseObject(pNetFwRule); 814 }
815 else if (fUpdateRule)
816 {
817 hr = pNetFwRule->put_ApplicationName(NULL);
818 ExitOnFailure(hr, "failed to remove exception application name");
819 }
346 820
347 return hr; 821 if (MSI_NULL_INTEGER != attrs.iEdgeTraversal)
348} 822 {
823 switch (attrs.iEdgeTraversal)
824 {
825 default:
826 hr = pNetFwRule->put_EdgeTraversal(NET_FW_EDGE_TRAVERSAL_TYPE_DENY != attrs.iEdgeTraversal ? VARIANT_TRUE : VARIANT_FALSE);
827 ExitOnFailure(hr, "failed to set exception edge traversal");
828 break;
349 829
350/****************************************************************** 830 // handled by put_EdgeTraversalOptions
351 AddApplicationException 831 case NET_FW_EDGE_TRAVERSAL_TYPE_DEFER_TO_APP:
832 case NET_FW_EDGE_TRAVERSAL_TYPE_DEFER_TO_USER:
833 break;
834 }
835 }
836 else if (fUpdateRule)
837 {
838 hr = pNetFwRule->put_EdgeTraversal(VARIANT_FALSE);
839 ExitOnFailure(hr, "failed to remove exception edge traversal");
840 }
352 841
353********************************************************************/ 842 // enable even when iEnabled == MSI_NULL_INTEGER
354static HRESULT AddApplicationException( 843 hr = pNetFwRule->put_Enabled(attrs.iEnabled ? VARIANT_TRUE : VARIANT_FALSE);
355 __in FIREWALL_EXCEPTION_ATTRIBUTES const& attrs, 844 ExitOnFailure(hr, "failed to set exception enabled flag");
356 __in BOOL fIgnoreFailures
357 )
358{
359 HRESULT hr = S_OK;
360 BSTR bstrFile = NULL;
361 BSTR bstrName = NULL;
362 INetFwRules* pNetFwRules = NULL;
363 INetFwRule* pNetFwRule = NULL;
364 845
365 // convert to BSTRs to make COM happy 846 if (bstrGrouping && *bstrGrouping)
366 bstrFile = ::SysAllocString(attrs.pwzProgram); 847 {
367 ExitOnNull(bstrFile, hr, E_OUTOFMEMORY, "failed SysAllocString for path"); 848 hr = pNetFwRule->put_Grouping(bstrGrouping);
368 bstrName = ::SysAllocString(attrs.pwzName); 849 ExitOnFailure(hr, "failed to set exception grouping '%ls'", bstrGrouping);
369 ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "failed SysAllocString for name"); 850 }
851 else if (fUpdateRule)
852 {
853 hr = pNetFwRule->put_Grouping(bstrEmpty);
854 ExitOnFailure(hr, "failed to remove exception grouping");
855 }
370 856
371 // get the collection of firewall rules 857 if (bstrIcmpTypesAndCodes && *bstrIcmpTypesAndCodes)
372 hr = GetFirewallRules(fIgnoreFailures, &pNetFwRules);
373 ExitOnFailure(hr, "failed to get firewall rules object");
374 if (S_FALSE == hr) // user or package author chose to ignore missing firewall
375 { 858 {
376 ExitFunction(); 859 hr = pNetFwRule->put_IcmpTypesAndCodes(bstrIcmpTypesAndCodes);
860 ExitOnFailure(hr, "failed to set exception icmp types and codes '%ls'", bstrIcmpTypesAndCodes);
377 } 861 }
378 862
379 // try to find it (i.e., support reinstall) 863 hr = GetFwRuleInterfaces(attrs, vInterfaces);
380 hr = pNetFwRules->Item(bstrName, &pNetFwRule); 864 ExitOnFailure(hr, "failed to prepare exception interfaces '%ls'", attrs.pwzInterfaces);
381 if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) 865
866 if (attrs.pwzInterfaces && *attrs.pwzInterfaces)
382 { 867 {
383 hr = CreateFwRuleObject(bstrName, attrs, &pNetFwRule); 868 hr = pNetFwRule->put_Interfaces(vInterfaces);
384 ExitOnFailure(hr, "failed to create FwRule object"); 869 ExitOnFailure(hr, "failed to set exception interfaces '%ls'", attrs.pwzInterfaces);
870 }
871 else if (fUpdateRule)
872 {
873 hr = pNetFwRule->put_Interfaces(vInterfaces);
874 ExitOnFailure(hr, "failed to remove exception interfaces");
875 }
385 876
386 // set edge traversal to true 877 if (bstrInterfaceTypes && *bstrInterfaceTypes)
387 hr = pNetFwRule->put_EdgeTraversal(VARIANT_TRUE); 878 {
388 ExitOnFailure(hr, "failed to set application exception edgetraversal property"); 879 hr = pNetFwRule->put_InterfaceTypes(bstrInterfaceTypes);
389 880 ExitOnFailure(hr, "failed to set exception interface types '%ls'", bstrInterfaceTypes);
390 // set path
391 hr = pNetFwRule->put_ApplicationName(bstrFile);
392 ExitOnFailure(hr, "failed to set application name");
393
394 // enable it
395 hr = pNetFwRule->put_Enabled(VARIANT_TRUE);
396 ExitOnFailure(hr, "failed to to enable application exception");
397
398 // add it to the list of authorized apps
399 hr = pNetFwRules->Add(pNetFwRule);
400 ExitOnFailure(hr, "failed to add app to the authorized apps list");
401 } 881 }
402 else 882 else if (fUpdateRule)
403 { 883 {
404 // we found an existing app exception (if we succeeded, that is) 884 hr = pNetFwRule->put_InterfaceTypes(bstrEmpty);
405 ExitOnFailure(hr, "failed trying to find existing app"); 885 ExitOnFailure(hr, "failed to remove exception interface types");
406 886 }
407 // enable it (just in case it was disabled) 887
408 pNetFwRule->put_Enabled(VARIANT_TRUE); 888 if (bstrLocalAddresses && *bstrLocalAddresses)
889 {
890 hr = pNetFwRule->put_LocalAddresses(bstrLocalAddresses);
891 ExitOnFailure(hr, "failed to set exception local addresses '%ls'", bstrLocalAddresses);
892 }
893 else if (fUpdateRule)
894 {
895 hr = pNetFwRule->put_LocalAddresses(bstrEmpty);
896 ExitOnFailure(hr, "failed to remove exception local addresses");
897 }
898
899 if (bstrRemotePort && *bstrRemotePort)
900 {
901 hr = pNetFwRule->put_RemotePorts(bstrRemotePort);
902 ExitOnFailure(hr, "failed to set exception remote ports '%ls'", bstrRemotePort);
903 }
904
905 if (bstrServiceName && *bstrServiceName)
906 {
907 hr = pNetFwRule->put_ServiceName(bstrServiceName);
908 ExitOnFailure(hr, "failed to set exception service name '%ls'", bstrServiceName);
909 }
910 else if (fUpdateRule)
911 {
912 hr = pNetFwRule->put_ServiceName(NULL);
913 ExitOnFailure(hr, "failed to remove exception service name");
409 } 914 }
410 915
411LExit: 916LExit:
412 ReleaseBSTR(bstrName); 917 ReleaseBSTR(bstrRemoteAddresses);
413 ReleaseBSTR(bstrFile); 918 ReleaseBSTR(bstrFile);
414 ReleaseObject(pNetFwRules); 919 ReleaseBSTR(bstrPort);
415 ReleaseObject(pNetFwRule); 920 ReleaseBSTR(bstrDescription);
921 ReleaseBSTR(bstrGrouping);
922 ReleaseBSTR(bstrIcmpTypesAndCodes);
923 ReleaseBSTR(bstrInterfaceTypes);
924 ReleaseBSTR(bstrLocalAddresses);
925 ReleaseBSTR(bstrRemotePort);
926 ReleaseBSTR(bstrServiceName);
927 ReleaseVariant(vInterfaces);
928 ReleaseObject(pNetFwRule2);
416 929
417 return fIgnoreFailures ? S_OK : hr; 930 return hr;
418} 931}
419 932
420/****************************************************************** 933
421 AddPortException 934/*******************************************************************
935 AddFirewallException
422 936
423********************************************************************/ 937********************************************************************/
424static HRESULT AddPortException( 938static HRESULT AddFirewallException(
425 __in FIREWALL_EXCEPTION_ATTRIBUTES const& attrs, 939 __in FIREWALL_EXCEPTION_ATTRIBUTES const& attrs,
426 __in BOOL fIgnoreFailures 940 __in BOOL fIgnoreFailures
427 ) 941)
428{ 942{
429 HRESULT hr = S_OK; 943 HRESULT hr = S_OK;
430 BSTR bstrName = NULL; 944 BSTR bstrName = NULL;
431 INetFwRules* pNetFwRules = NULL; 945 INetFwRules* pNetFwRules = NULL;
432 INetFwRule* pNetFwRule = NULL; 946 INetFwRule* pNetFwRule = NULL;
433 947
948 BOOL fIgnoreUpdates = feaIgnoreUpdates == (attrs.iAttributes & feaIgnoreUpdates);
949 BOOL fEnableOnUpdate = feaEnableOnUpdate == (attrs.iAttributes & feaEnableOnUpdate);
950 BOOL fAddINetFwRule2 = feaAddINetFwRule2 == (attrs.iAttributes & feaAddINetFwRule2);
951 BOOL fAddINetFwRule3 = feaAddINetFwRule3 == (attrs.iAttributes & feaAddINetFwRule3);
952
434 // convert to BSTRs to make COM happy 953 // convert to BSTRs to make COM happy
435 bstrName = ::SysAllocString(attrs.pwzName); 954 bstrName = ::SysAllocString(attrs.pwzName);
436 ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "failed SysAllocString for name"); 955 ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "failed SysAllocString for name");
437 956
438 // get the collection of firewall rules 957 // get the collection of firewall rules
439 hr = GetFirewallRules(fIgnoreFailures, &pNetFwRules); 958 hr = GetFirewallRules(fIgnoreFailures, &pNetFwRules);
440 ExitOnFailure(hr, "failed to get firewall rules object"); 959 ExitOnFailure(hr, "failed to get firewall exception object");
441 if (S_FALSE == hr) // user or package author chose to ignore missing firewall 960 if (S_FALSE == hr) // user or package author chose to ignore missing firewall
442 { 961 {
443 ExitFunction(); 962 ExitFunction();
@@ -447,24 +966,56 @@ static HRESULT AddPortException(
447 hr = pNetFwRules->Item(bstrName, &pNetFwRule); 966 hr = pNetFwRules->Item(bstrName, &pNetFwRule);
448 if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) 967 if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
449 { 968 {
450 hr = CreateFwRuleObject(bstrName, attrs, &pNetFwRule); 969 hr = CreateFwRuleObject(bstrName, &pNetFwRule);
451 ExitOnFailure(hr, "failed to create FwRule object"); 970 ExitOnFailure(hr, "failed to create FwRule object '%ls'", attrs.pwzName);
452 971
453 // enable it 972 // set attributes of the new firewall rule
454 hr = pNetFwRule->put_Enabled(VARIANT_TRUE); 973 hr = UpdateFwRuleObject(pNetFwRule, FALSE, attrs);
455 ExitOnFailure(hr, "failed to to enable port exception"); 974 ExitOnFailure(hr, "failed to create INetFwRule firewall exception '%ls'", attrs.pwzName);
975
976 if (fAddINetFwRule2)
977 {
978 hr = UpdateFwRule2Object(pNetFwRule, FALSE, attrs);
979 ExitOnFailure(hr, "failed to create INetFwRule2 firewall exception '%ls'", attrs.pwzName);
980 }
981
982 if (fAddINetFwRule3)
983 {
984 hr = UpdateFwRule3Object(pNetFwRule, FALSE, attrs);
985 ExitOnFailure(hr, "failed to create INetFwRule3 firewall exception '%ls'", attrs.pwzName);
986 }
456 987
457 // add it to the list of authorized ports
458 hr = pNetFwRules->Add(pNetFwRule); 988 hr = pNetFwRules->Add(pNetFwRule);
459 ExitOnFailure(hr, "failed to add app to the authorized ports list"); 989 ExitOnFailure(hr, "failed to add firewall exception '%ls' to the list", attrs.pwzName);
460 } 990 }
461 else 991 else
462 { 992 {
463 // we found an existing port exception (if we succeeded, that is) 993 // we found an existing firewall rule (if we succeeded, that is)
464 ExitOnFailure(hr, "failed trying to find existing port rule"); 994 ExitOnFailure(hr, "failed trying to find existing firewall exception '%ls'", attrs.pwzName);
995
996 if (fEnableOnUpdate)
997 {
998 hr = pNetFwRule->put_Enabled(VARIANT_TRUE);
999 ExitOnFailure(hr, "failed to enable existing firewall exception '%ls'", attrs.pwzName);
1000 }
1001 else if (!fIgnoreUpdates)
1002 {
1003 // overwrite attributes of the existing firewall rule
1004 hr = UpdateFwRuleObject(pNetFwRule, TRUE, attrs);
1005 ExitOnFailure(hr, "failed to update INetFwRule firewall exception '%ls'", attrs.pwzName);
465 1006
466 // enable it (just in case it was disabled) 1007 if (fAddINetFwRule2)
467 pNetFwRule->put_Enabled(VARIANT_TRUE); 1008 {
1009 hr = UpdateFwRule2Object(pNetFwRule, TRUE, attrs);
1010 ExitOnFailure(hr, "failed to update INetFwRule2 firewall exception '%ls'", attrs.pwzName);
1011 }
1012
1013 if (fAddINetFwRule3)
1014 {
1015 hr = UpdateFwRule3Object(pNetFwRule, TRUE, attrs);
1016 ExitOnFailure(hr, "failed to update INetFwRule3 firewall exception '%ls'", attrs.pwzName);
1017 }
1018 }
468 } 1019 }
469 1020
470LExit: 1021LExit:
@@ -475,14 +1026,15 @@ LExit:
475 return fIgnoreFailures ? S_OK : hr; 1026 return fIgnoreFailures ? S_OK : hr;
476} 1027}
477 1028
478/****************************************************************** 1029
1030/*******************************************************************
479 RemoveException - Removes all exception rules with the given name. 1031 RemoveException - Removes all exception rules with the given name.
480 1032
481********************************************************************/ 1033********************************************************************/
482static HRESULT RemoveException( 1034static HRESULT RemoveException(
483 __in LPCWSTR wzName, 1035 __in LPCWSTR wzName,
484 __in BOOL fIgnoreFailures 1036 __in BOOL fIgnoreFailures
485 ) 1037)
486{ 1038{
487 HRESULT hr = S_OK;; 1039 HRESULT hr = S_OK;;
488 INetFwRules* pNetFwRules = NULL; 1040 INetFwRules* pNetFwRules = NULL;
@@ -500,7 +1052,7 @@ static HRESULT RemoveException(
500 } 1052 }
501 1053
502 hr = pNetFwRules->Remove(bstrName); 1054 hr = pNetFwRules->Remove(bstrName);
503 ExitOnFailure(hr, "failed to remove firewall rule"); 1055 ExitOnFailure(hr, "failed to remove firewall exception for name %ls", wzName);
504 1056
505LExit: 1057LExit:
506 ReleaseBSTR(bstrName); 1058 ReleaseBSTR(bstrName);
@@ -509,20 +1061,20 @@ LExit:
509 return fIgnoreFailures ? S_OK : hr; 1061 return fIgnoreFailures ? S_OK : hr;
510} 1062}
511 1063
512/****************************************************************** 1064
513 ExecFirewallExceptions - deferred custom action entry point to 1065/*******************************************************************
1066 ExecFirewallExceptions - deferred custom action entry point to
514 register and remove firewall exceptions. 1067 register and remove firewall exceptions.
515 1068
516********************************************************************/ 1069********************************************************************/
517extern "C" UINT __stdcall ExecFirewallExceptions( 1070extern "C" UINT __stdcall ExecFirewallExceptions(
518 __in MSIHANDLE hInstall 1071 __in MSIHANDLE hInstall
519 ) 1072)
520{ 1073{
521 HRESULT hr = S_OK; 1074 HRESULT hr = S_OK;
522 LPWSTR pwz = NULL; 1075 LPWSTR pwz = NULL;
523 LPWSTR pwzCustomActionData = NULL; 1076 LPWSTR pwzCustomActionData = NULL;
524 int iTodo = WCA_TODO_UNKNOWN; 1077 int iTodo = WCA_TODO_UNKNOWN;
525 int iTarget = fetUnknown;
526 1078
527 FIREWALL_EXCEPTION_ATTRIBUTES attrs = { 0 }; 1079 FIREWALL_EXCEPTION_ATTRIBUTES attrs = { 0 };
528 1080
@@ -530,7 +1082,7 @@ extern "C" UINT __stdcall ExecFirewallExceptions(
530 hr = WcaInitialize(hInstall, "ExecFirewallExceptions"); 1082 hr = WcaInitialize(hInstall, "ExecFirewallExceptions");
531 ExitOnFailure(hr, "failed to initialize"); 1083 ExitOnFailure(hr, "failed to initialize");
532 1084
533 hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData); 1085 hr = WcaGetProperty(L"CustomActionData", &pwzCustomActionData);
534 ExitOnFailure(hr, "failed to get CustomActionData"); 1086 ExitOnFailure(hr, "failed to get CustomActionData");
535 WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData); 1087 WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData);
536 1088
@@ -569,60 +1121,82 @@ extern "C" UINT __stdcall ExecFirewallExceptions(
569 ExitOnFailure(hr, "failed to read attributes from custom action data"); 1121 ExitOnFailure(hr, "failed to read attributes from custom action data");
570 BOOL fIgnoreFailures = feaIgnoreFailures == (attrs.iAttributes & feaIgnoreFailures); 1122 BOOL fIgnoreFailures = feaIgnoreFailures == (attrs.iAttributes & feaIgnoreFailures);
571 1123
572 hr = WcaReadIntegerFromCaData(&pwz, &iTarget); 1124 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzApplicationName);
573 ExitOnFailure(hr, "failed to read target from custom action data"); 1125 ExitOnFailure(hr, "failed to read file path from custom action data");
574 1126
575 if (iTarget == fetApplication) 1127 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzLocalPorts);
576 {
577 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzProgram);
578 ExitOnFailure(hr, "failed to read file path from custom action data");
579 }
580
581 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzPort);
582 ExitOnFailure(hr, "failed to read port from custom action data"); 1128 ExitOnFailure(hr, "failed to read port from custom action data");
1129
583 hr = WcaReadIntegerFromCaData(&pwz, &attrs.iProtocol); 1130 hr = WcaReadIntegerFromCaData(&pwz, &attrs.iProtocol);
584 ExitOnFailure(hr, "failed to read protocol from custom action data"); 1131 ExitOnFailure(hr, "failed to read protocol from custom action data");
1132
585 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzDescription); 1133 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzDescription);
586 ExitOnFailure(hr, "failed to read protocol from custom action data"); 1134 ExitOnFailure(hr, "failed to read protocol from custom action data");
1135
587 hr = WcaReadIntegerFromCaData(&pwz, &attrs.iDirection); 1136 hr = WcaReadIntegerFromCaData(&pwz, &attrs.iDirection);
588 ExitOnFailure(hr, "failed to read direction from custom action data"); 1137 ExitOnFailure(hr, "failed to read direction from custom action data");
589 1138
590 switch (iTarget) 1139 hr = WcaReadIntegerFromCaData(&pwz, &attrs.iAction);
591 { 1140 ExitOnFailure(hr, "failed to read action from custom action data");
592 case fetPort:
593 switch (iTodo)
594 {
595 case WCA_TODO_INSTALL:
596 case WCA_TODO_REINSTALL:
597 WcaLog(LOGMSG_STANDARD, "Installing firewall exception %ls on port %ls, protocol %d", attrs.pwzName, attrs.pwzPort, attrs.iProtocol);
598 hr = AddPortException(attrs, fIgnoreFailures);
599 ExitOnFailure(hr, "failed to add/update port exception for name '%ls' on port %ls, protocol %d", attrs.pwzName, attrs.pwzPort, attrs.iProtocol);
600 break;
601 1141
602 case WCA_TODO_UNINSTALL: 1142 hr = WcaReadIntegerFromCaData(&pwz, &attrs.iEdgeTraversal);
603 WcaLog(LOGMSG_STANDARD, "Uninstalling firewall exception %ls on port %ls, protocol %d", attrs.pwzName, attrs.pwzPort, attrs.iProtocol); 1143 ExitOnFailure(hr, "failed to read edge traversal from custom action data");
604 hr = RemoveException(attrs.pwzName, fIgnoreFailures);
605 ExitOnFailure(hr, "failed to remove port exception for name '%ls' on port %ls, protocol %d", attrs.pwzName, attrs.pwzPort, attrs.iProtocol);
606 break;
607 }
608 break;
609 1144
610 case fetApplication: 1145 hr = WcaReadIntegerFromCaData(&pwz, &attrs.iEnabled);
611 switch (iTodo) 1146 ExitOnFailure(hr, "failed to read enabled flag from custom action data");
612 {
613 case WCA_TODO_INSTALL:
614 case WCA_TODO_REINSTALL:
615 WcaLog(LOGMSG_STANDARD, "Installing firewall exception %ls (%ls)", attrs.pwzName, attrs.pwzProgram);
616 hr = AddApplicationException(attrs, fIgnoreFailures);
617 ExitOnFailure(hr, "failed to add/update application exception for name '%ls', file '%ls'", attrs.pwzName, attrs.pwzProgram);
618 break;
619 1147
620 case WCA_TODO_UNINSTALL: 1148 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzGrouping);
621 WcaLog(LOGMSG_STANDARD, "Uninstalling firewall exception %ls (%ls)", attrs.pwzName, attrs.pwzProgram); 1149 ExitOnFailure(hr, "failed to read grouping from custom action data");
622 hr = RemoveException(attrs.pwzName, fIgnoreFailures); 1150
623 ExitOnFailure(hr, "failed to remove application exception for name '%ls', file '%ls'", attrs.pwzName, attrs.pwzProgram); 1151 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzIcmpTypesAndCodes);
624 break; 1152 ExitOnFailure(hr, "failed to read icmp types and codes from custom action data");
625 } 1153
1154 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzInterfaces);
1155 ExitOnFailure(hr, "failed to read interfaces from custom action data");
1156
1157 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzInterfaceTypes);
1158 ExitOnFailure(hr, "failed to read interface types from custom action data");
1159
1160 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzLocalAddresses);
1161 ExitOnFailure(hr, "failed to read local addresses from custom action data");
1162
1163 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzRemotePorts);
1164 ExitOnFailure(hr, "failed to read remote port from custom action data");
1165
1166 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzServiceName);
1167 ExitOnFailure(hr, "failed to read service name from custom action data");
1168
1169 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzLocalAppPackageId);
1170 ExitOnFailure(hr, "failed to read local app package id from custom action data");
1171
1172 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzLocalUserAuthorizedList);
1173 ExitOnFailure(hr, "failed to read local user authorized list from custom action data");
1174
1175 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzLocalUserOwner);
1176 ExitOnFailure(hr, "failed to read local user owner from custom action data");
1177
1178 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzRemoteMachineAuthorizedList);
1179 ExitOnFailure(hr, "failed to read remote machine authorized list from custom action data");
1180
1181 hr = WcaReadStringFromCaData(&pwz, &attrs.pwzRemoteUserAuthorizedList);
1182 ExitOnFailure(hr, "failed to read remote user authorized list from custom action data");
1183
1184 hr = WcaReadIntegerFromCaData(&pwz, &attrs.iSecureFlags);
1185 ExitOnFailure(hr, "failed to read exception secure flags from custom action data");
1186
1187 switch (iTodo)
1188 {
1189 case WCA_TODO_INSTALL:
1190 case WCA_TODO_REINSTALL:
1191 WcaLog(LOGMSG_STANDARD, "Installing firewall exception %ls", attrs.pwzName);
1192 hr = AddFirewallException(attrs, fIgnoreFailures);
1193 ExitOnFailure(hr, "failed to add/update firewall exception for name '%ls'", attrs.pwzName);
1194 break;
1195
1196 case WCA_TODO_UNINSTALL:
1197 WcaLog(LOGMSG_STANDARD, "Uninstalling firewall exception %ls", attrs.pwzName);
1198 hr = RemoveException(attrs.pwzName, fIgnoreFailures);
1199 ExitOnFailure(hr, "failed to remove firewall exception");
626 break; 1200 break;
627 } 1201 }
628 } 1202 }
@@ -631,9 +1205,21 @@ LExit:
631 ReleaseStr(pwzCustomActionData); 1205 ReleaseStr(pwzCustomActionData);
632 ReleaseStr(attrs.pwzName); 1206 ReleaseStr(attrs.pwzName);
633 ReleaseStr(attrs.pwzRemoteAddresses); 1207 ReleaseStr(attrs.pwzRemoteAddresses);
634 ReleaseStr(attrs.pwzProgram); 1208 ReleaseStr(attrs.pwzApplicationName);
635 ReleaseStr(attrs.pwzPort); 1209 ReleaseStr(attrs.pwzLocalPorts);
636 ReleaseStr(attrs.pwzDescription); 1210 ReleaseStr(attrs.pwzDescription);
1211 ReleaseStr(attrs.pwzGrouping);
1212 ReleaseStr(attrs.pwzIcmpTypesAndCodes);
1213 ReleaseStr(attrs.pwzInterfaces);
1214 ReleaseStr(attrs.pwzInterfaceTypes);
1215 ReleaseStr(attrs.pwzLocalAddresses);
1216 ReleaseStr(attrs.pwzRemotePorts);
1217 ReleaseStr(attrs.pwzServiceName);
1218 ReleaseStr(attrs.pwzLocalAppPackageId);
1219 ReleaseStr(attrs.pwzLocalUserAuthorizedList);
1220 ReleaseStr(attrs.pwzLocalUserOwner);
1221 ReleaseStr(attrs.pwzRemoteMachineAuthorizedList);
1222 ReleaseStr(attrs.pwzRemoteUserAuthorizedList);
637 ::CoUninitialize(); 1223 ::CoUninitialize();
638 1224
639 return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILURE : ERROR_SUCCESS); 1225 return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILURE : ERROR_SUCCESS);
diff --git a/src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs b/src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs
index 7119e92d..df18f0e0 100644
--- a/src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs
+++ b/src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs
@@ -2,6 +2,7 @@
2 2
3namespace WixToolsetTest.Firewall 3namespace WixToolsetTest.Firewall
4{ 4{
5 using System.Data;
5 using System.IO; 6 using System.IO;
6 using System.Linq; 7 using System.Linq;
7 using System.Xml.Linq; 8 using System.Xml.Linq;
@@ -27,12 +28,27 @@ namespace WixToolsetTest.Firewall
27 "CustomAction:Wix5RollbackFirewallExceptionsUninstall_X86\t3329\tWix5FWCA_X86\tExecFirewallExceptions\t", 28 "CustomAction:Wix5RollbackFirewallExceptionsUninstall_X86\t3329\tWix5FWCA_X86\tExecFirewallExceptions\t",
28 "CustomAction:Wix5SchedFirewallExceptionsInstall_X86\t1\tWix5FWCA_X86\tSchedFirewallExceptionsInstall\t", 29 "CustomAction:Wix5SchedFirewallExceptionsInstall_X86\t1\tWix5FWCA_X86\tSchedFirewallExceptionsInstall\t",
29 "CustomAction:Wix5SchedFirewallExceptionsUninstall_X86\t1\tWix5FWCA_X86\tSchedFirewallExceptionsUninstall\t", 30 "CustomAction:Wix5SchedFirewallExceptionsUninstall_X86\t1\tWix5FWCA_X86\tSchedFirewallExceptionsUninstall\t",
30 "Wix5FirewallException:ExampleFirewall\tExampleApp\t*\t42\t6\t[#filNdJBJmq3UCUIwmXS8x21aAsvqzk]\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tAn app-based firewall exception\t1", 31 "Wix5FirewallException:ExampleFirewall\tExampleApp\t*\t42\t6\t[#filNdJBJmq3UCUIwmXS8x21aAsvqzk]\t2\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tAn app-based firewall exception\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
31 "Wix5FirewallException:fex_ZpDsnKyHlYiA24JHzvFxm3uLZ8\tExampleDefaultGatewayScope\tDefaultGateway\t4432\t6\t\t0\t2\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tdefaultGateway scope firewall exception\t1", 32 "Wix5FirewallException:fex.BGtyMRGAhxb2hG.49JvWYz7fM0\tLocalScopeExample2\t*\t\t-2147483648\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tRule with local scope property\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t[LOCALSCOPE_PROP]\t\t\t\t\t\t\t\t-2147483648",
32 "Wix5FirewallException:fex6bkfWwpiRGI.wVFx0T7W4LXIHxU\tExampleDHCPScope\tdhcp\t\t211\ttest.exe\t0\t4\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tDHCP scope firewall exception\t1", 33 "Wix5FirewallException:fex0HTxATWjpC2PCoY6DB7f2D1WaKU\tLocalScopeExample1\t*\t\t-2147483648\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tSimple rule with local scope\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\tLocalSubnet\t\t\t\t\t\t\t\t-2147483648",
33 "Wix5FirewallException:fex70IVsYNnbwiHQrEepmdTPKH8XYs\tExamplePort\tLocalSubnet\t42\t6\t\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tA port-based firewall exception\t2", 34 "Wix5FirewallException:fex4FeP470wYcFpw.g7fbIKiLnZPzg\tExampleDNSScope\tdns\t356\t17\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tDNS scope firewall exception\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
34 "Wix5FirewallException:fexXxaXCXXFh.UxO_BjmZxi1B1du_Q\tExampleWINSScope\twins\t6573\t6\t\t0\t1\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tWINS scope firewall exception\t1", 35 "Wix5FirewallException:fex4zTcT0Iwu3dUtHIHXD5qfymvpcM\tdefertouser\t\t\t-2147483648\tfw.exe\t8\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tDefer to user edge traversal\t1\t-2147483648\t3\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
35 "Wix5FirewallException:fexxY71H2ZBkPalv7uid1Yy4qaA_lA\tExampleDNSScope\tdns\t356\t17\t\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tDNS scope firewall exception\t1", 36 "Wix5FirewallException:fex8vMfBplrod4daEz3PqDTeX6olGE\tExampleDefaultGatewayScope\tDefaultGateway\t4432\t6\t\t0\t2\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tdefaultGateway scope firewall exception\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
37 "Wix5FirewallException:fexAMmHzFDyQmubTOnKS1Cn0Y3q_Ug\tINetFwRule3 properties\t*\t\t-2147483648\t\t16\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tINetFwRule3 passed via properties\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t[PROP1]\t[PROP2]\t[PROP3]\t[PROP4]\t[PROP5]\t[PROP6]",
38 "Wix5FirewallException:fexArlOkFR7CAwVZ2wk8yNdiREydu0\tRemotePortExample2\t\t\t6\tfw.exe\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tRule with remote port property\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t[REMOTEPORT_PROP]\t\t\t\t\t\t\t-2147483648",
39 "Wix5FirewallException:fexaUTe2tRRcSYrPUTn44DAZhE.40Q\tExamplePort\tLocalSubnet\t42\t6\t\t4\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tA port-based firewall exception\t2\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
40 "Wix5FirewallException:fexD6w20c5HfNi4l1vHFj_eet4cC8I\tExampleWINSScope\twins\t6573\t6\t\t0\t1\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tWINS scope firewall exception\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
41 "Wix5FirewallException:fexeD3yox6fMflfRy7sDwSN2CMCS2s\tExampleService\t\t12000\t6\t%windir%\\system32\\svchost.exe\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tA port-based service exception\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\tDHCP,WINS\t\tftpsrv\t\t\t\t\t\t-2147483648",
42 "Wix5FirewallException:fexeok6aI2_AlclZggec4d8PBLFXLw\tinterface property\t\t54671\t6\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tInterfaces with property\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t[INTERFACE_PROPERTY]\t\t\t\t\t\t\t\t\t\t-2147483648",
43 "Wix5FirewallException:fexEPvcf4iexD1mVQdvxm7tD02nZEc\tICMPExample1\t\t\t2\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tSimple ICMP rule\t1\t-2147483648\t-2147483648\t-2147483648\t\t4:*,9:*,12:*\t\t\t\t\t\t\t\t\t\t\t-2147483648",
44 "Wix5FirewallException:fexfzjTQsWwZkHQpObtl0XaUosfcRk\tGroupingExample1\t\t\t-2147483648\tfw.exe\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tSimple rule with grouping\t1\t-2147483648\t-2147483648\t-2147483648\t@yourresources.dll,-1005\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
45 "Wix5FirewallException:fexHx2xbwZYzAi0oYp4YGWevJQs5eM\tRemotePortExample1\t*\t\t6\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tSimple rule with remote port\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t34560\t\t\t\t\t\t\t-2147483648",
46 "Wix5FirewallException:fexpWUzK53RVnaluW36gSmphPRY8VY\tExampleDHCPScope\tdhcp\t\t211\ttest.exe\t0\t4\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tDHCP scope firewall exception\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
47 "Wix5FirewallException:fexuanTga5xaaFzr9JsAnUmpCNediw\tICMPExample2\t\t\t2\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tRule with ICMP property\t1\t-2147483648\t-2147483648\t-2147483648\t\t[ICMP_PROP]\t\t\t\t\t\t\t\t\t\t\t-2147483648",
48 "Wix5FirewallException:fexv60s7u2Dmd1imH5vEFYKPgEWhG4\tinterface nested\t127.0.0.1\t54671\t6\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tInterfaces with nested elements\t1\t-2147483648\t-2147483648\t-2147483648\t\t\tWi-Fi|Local Area Connection\t\t\t\t\t\t\t\t\t\t-2147483648",
49 "Wix5FirewallException:fexVr6uHcOCak5MHuTLwujjh_oKtbI\tGroupingExample2\t\t8732\t6\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tRule with grouping property\t1\t-2147483648\t-2147483648\t-2147483648\t[GROUPING_PROP]\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
50 "Wix5FirewallException:fexwjf4OTFVE9SNiC4goVxBA6ENJBE\tINetFwRule3 values\t*\t\t-2147483648\t\t16\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tSimple INetFwRule3 values\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\tS-1-15-2-1239072475-3687740317-1842961305-3395936705-4023953123-1525404051-2779347315\tO:LSD:(A;;CC;;;S-1-5-84-0-0-0-0-0)\tS-1-5-21-1898747406-2352535518-1247798438-1914\t127.0.0.1\tO:LSD:(A;;CC;;;S-1-5-84-0-0-0-0-0)\t3",
51 "Wix5FirewallException:ServiceInstall.nested\tExampleNestedService\tLocalSubnet\t3546-7890\t6\t\t1\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tA port-based firewall exception for a windows service\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\tLan,Wireless\t\t\tsvc1\t\t\t\t\t\t-2147483648",
36 }, results); 52 }, results);
37 } 53 }
38 54
@@ -51,12 +67,69 @@ namespace WixToolsetTest.Firewall
51 "CustomAction:Wix5RollbackFirewallExceptionsUninstall_A64\t3329\tWix5FWCA_A64\tExecFirewallExceptions\t", 67 "CustomAction:Wix5RollbackFirewallExceptionsUninstall_A64\t3329\tWix5FWCA_A64\tExecFirewallExceptions\t",
52 "CustomAction:Wix5SchedFirewallExceptionsInstall_A64\t1\tWix5FWCA_A64\tSchedFirewallExceptionsInstall\t", 68 "CustomAction:Wix5SchedFirewallExceptionsInstall_A64\t1\tWix5FWCA_A64\tSchedFirewallExceptionsInstall\t",
53 "CustomAction:Wix5SchedFirewallExceptionsUninstall_A64\t1\tWix5FWCA_A64\tSchedFirewallExceptionsUninstall\t", 69 "CustomAction:Wix5SchedFirewallExceptionsUninstall_A64\t1\tWix5FWCA_A64\tSchedFirewallExceptionsUninstall\t",
54 "Wix5FirewallException:ExampleFirewall\tExampleApp\t*\t42\t6\t[#filNdJBJmq3UCUIwmXS8x21aAsvqzk]\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tAn app-based firewall exception\t1", 70 "Wix5FirewallException:ExampleFirewall\tExampleApp\t*\t42\t6\t[#filNdJBJmq3UCUIwmXS8x21aAsvqzk]\t2\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tAn app-based firewall exception\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
55 "Wix5FirewallException:fex_ZpDsnKyHlYiA24JHzvFxm3uLZ8\tExampleDefaultGatewayScope\tDefaultGateway\t4432\t6\t\t0\t2\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tdefaultGateway scope firewall exception\t1", 71 "Wix5FirewallException:fex.BGtyMRGAhxb2hG.49JvWYz7fM0\tLocalScopeExample2\t*\t\t-2147483648\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tRule with local scope property\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t[LOCALSCOPE_PROP]\t\t\t\t\t\t\t\t-2147483648",
56 "Wix5FirewallException:fex6bkfWwpiRGI.wVFx0T7W4LXIHxU\tExampleDHCPScope\tdhcp\t\t211\ttest.exe\t0\t4\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tDHCP scope firewall exception\t1", 72 "Wix5FirewallException:fex0HTxATWjpC2PCoY6DB7f2D1WaKU\tLocalScopeExample1\t*\t\t-2147483648\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tSimple rule with local scope\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\tLocalSubnet\t\t\t\t\t\t\t\t-2147483648",
57 "Wix5FirewallException:fex70IVsYNnbwiHQrEepmdTPKH8XYs\tExamplePort\tLocalSubnet\t42\t6\t\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tA port-based firewall exception\t2", 73 "Wix5FirewallException:fex4FeP470wYcFpw.g7fbIKiLnZPzg\tExampleDNSScope\tdns\t356\t17\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tDNS scope firewall exception\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
58 "Wix5FirewallException:fexXxaXCXXFh.UxO_BjmZxi1B1du_Q\tExampleWINSScope\twins\t6573\t6\t\t0\t1\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tWINS scope firewall exception\t1", 74 "Wix5FirewallException:fex4zTcT0Iwu3dUtHIHXD5qfymvpcM\tdefertouser\t\t\t-2147483648\tfw.exe\t8\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tDefer to user edge traversal\t1\t-2147483648\t3\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
59 "Wix5FirewallException:fexxY71H2ZBkPalv7uid1Yy4qaA_lA\tExampleDNSScope\tdns\t356\t17\t\t0\t2147483647\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tDNS scope firewall exception\t1", 75 "Wix5FirewallException:fex8vMfBplrod4daEz3PqDTeX6olGE\tExampleDefaultGatewayScope\tDefaultGateway\t4432\t6\t\t0\t2\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tdefaultGateway scope firewall exception\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
76 "Wix5FirewallException:fexAMmHzFDyQmubTOnKS1Cn0Y3q_Ug\tINetFwRule3 properties\t*\t\t-2147483648\t\t16\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tINetFwRule3 passed via properties\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t[PROP1]\t[PROP2]\t[PROP3]\t[PROP4]\t[PROP5]\t[PROP6]",
77 "Wix5FirewallException:fexArlOkFR7CAwVZ2wk8yNdiREydu0\tRemotePortExample2\t\t\t6\tfw.exe\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tRule with remote port property\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t[REMOTEPORT_PROP]\t\t\t\t\t\t\t-2147483648",
78 "Wix5FirewallException:fexaUTe2tRRcSYrPUTn44DAZhE.40Q\tExamplePort\tLocalSubnet\t42\t6\t\t4\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tA port-based firewall exception\t2\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
79 "Wix5FirewallException:fexD6w20c5HfNi4l1vHFj_eet4cC8I\tExampleWINSScope\twins\t6573\t6\t\t0\t1\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tWINS scope firewall exception\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
80 "Wix5FirewallException:fexeD3yox6fMflfRy7sDwSN2CMCS2s\tExampleService\t\t12000\t6\t%windir%\\system32\\svchost.exe\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tA port-based service exception\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\tDHCP,WINS\t\tftpsrv\t\t\t\t\t\t-2147483648",
81 "Wix5FirewallException:fexeok6aI2_AlclZggec4d8PBLFXLw\tinterface property\t\t54671\t6\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tInterfaces with property\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t[INTERFACE_PROPERTY]\t\t\t\t\t\t\t\t\t\t-2147483648",
82 "Wix5FirewallException:fexEPvcf4iexD1mVQdvxm7tD02nZEc\tICMPExample1\t\t\t2\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tSimple ICMP rule\t1\t-2147483648\t-2147483648\t-2147483648\t\t4:*,9:*,12:*\t\t\t\t\t\t\t\t\t\t\t-2147483648",
83 "Wix5FirewallException:fexfzjTQsWwZkHQpObtl0XaUosfcRk\tGroupingExample1\t\t\t-2147483648\tfw.exe\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tSimple rule with grouping\t1\t-2147483648\t-2147483648\t-2147483648\t@yourresources.dll,-1005\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
84 "Wix5FirewallException:fexHx2xbwZYzAi0oYp4YGWevJQs5eM\tRemotePortExample1\t*\t\t6\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tSimple rule with remote port\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t34560\t\t\t\t\t\t\t-2147483648",
85 "Wix5FirewallException:fexpWUzK53RVnaluW36gSmphPRY8VY\tExampleDHCPScope\tdhcp\t\t211\ttest.exe\t0\t4\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tDHCP scope firewall exception\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
86 "Wix5FirewallException:fexuanTga5xaaFzr9JsAnUmpCNediw\tICMPExample2\t\t\t2\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tRule with ICMP property\t1\t-2147483648\t-2147483648\t-2147483648\t\t[ICMP_PROP]\t\t\t\t\t\t\t\t\t\t\t-2147483648",
87 "Wix5FirewallException:fexv60s7u2Dmd1imH5vEFYKPgEWhG4\tinterface nested\t127.0.0.1\t54671\t6\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tInterfaces with nested elements\t1\t-2147483648\t-2147483648\t-2147483648\t\t\tWi-Fi|Local Area Connection\t\t\t\t\t\t\t\t\t\t-2147483648",
88 "Wix5FirewallException:fexVr6uHcOCak5MHuTLwujjh_oKtbI\tGroupingExample2\t\t8732\t6\t\t0\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tRule with grouping property\t1\t-2147483648\t-2147483648\t-2147483648\t[GROUPING_PROP]\t\t\t\t\t\t\t\t\t\t\t\t-2147483648",
89 "Wix5FirewallException:fexwjf4OTFVE9SNiC4goVxBA6ENJBE\tINetFwRule3 values\t*\t\t-2147483648\t\t16\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tSimple INetFwRule3 values\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\t\t\t\t\tS-1-15-2-1239072475-3687740317-1842961305-3395936705-4023953123-1525404051-2779347315\tO:LSD:(A;;CC;;;S-1-5-84-0-0-0-0-0)\tS-1-5-21-1898747406-2352535518-1247798438-1914\t127.0.0.1\tO:LSD:(A;;CC;;;S-1-5-84-0-0-0-0-0)\t3",
90 "Wix5FirewallException:ServiceInstall.nested\tExampleNestedService\tLocalSubnet\t3546-7890\t6\t\t1\t-2147483648\tfilNdJBJmq3UCUIwmXS8x21aAsvqzk\tA port-based firewall exception for a windows service\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t\tLan,Wireless\t\t\tsvc1\t\t\t\t\t\t-2147483648",
91 }, results);
92 }
93
94 [Fact]
95 public void CanBuildWithProperties()
96 {
97 var folder = TestData.Get(@"TestData\UsingProperties");
98 var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder });
99
100 var results = build.BuildAndQuery(Build, "Wix5FirewallException", "CustomAction");
101 WixAssert.CompareLineByLine(new[]
102 {
103 "CustomAction:Wix5ExecFirewallExceptionsInstall_X86\t3073\tWix5FWCA_X86\tExecFirewallExceptions\t",
104 "CustomAction:Wix5ExecFirewallExceptionsUninstall_X86\t3073\tWix5FWCA_X86\tExecFirewallExceptions\t",
105 "CustomAction:Wix5RollbackFirewallExceptionsInstall_X86\t3329\tWix5FWCA_X86\tExecFirewallExceptions\t",
106 "CustomAction:Wix5RollbackFirewallExceptionsUninstall_X86\t3329\tWix5FWCA_X86\tExecFirewallExceptions\t",
107 "CustomAction:Wix5SchedFirewallExceptionsInstall_X86\t1\tWix5FWCA_X86\tSchedFirewallExceptionsInstall\t",
108 "CustomAction:Wix5SchedFirewallExceptionsUninstall_X86\t1\tWix5FWCA_X86\tSchedFirewallExceptionsUninstall\t",
109 "Wix5FirewallException:fexRrE4bS.DwUJQMvzX0ALEsx7jrZs\tSingle Nested properties\t[REMOTEADDRESS]\t\t-2147483648\t\t0\t-2147483648\tFirewallComponent\t\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t[INTERFACE]\t[INTERFACETYPE]\t[LOCALADDRESS]\t\t\t\t\t\t\t\t-2147483648",
110 "Wix5FirewallException:fexvEy1GfdOjHlKcvsguyqK6mvYKyk\t[NAME]\t[REMOTESCOPE]\t[LOCALPORT]\t[PROTOCOL]\t[PROGRAM]\t16\t[PROFILE]\tFirewallComponent\t[DESCRIPTION]\t1\t[ACTION]\t[EDGETRAVERSAL]\t[ENABLED]\t[GROUPING]\t[ICMPTYPES]\t[INTERFACE]\t[INTERFACETYPE]\t[LOCALSCOPE]\t[REMOTEPORT]\t[SERVICE]\t[PACKAGEID]\t[LOCALUSERS]\t[LOCALOWNER]\t[REMOTEMACHINES]\t[REMOTEUSERS]\t[SECUREFLAGS]",
111 "Wix5FirewallException:fexWywW3VGiEuG23FOv1YM6h7R6F5Q\tMultiple Nested properties\t[REMOTEADDRESS1],[REMOTEADDRESS2]\t\t-2147483648\t\t0\t-2147483648\tFirewallComponent\t\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t[INTERFACE1]|[INTERFACE2]\t[INTERFACETYPE1],[INTERFACETYPE2]\t[LOCALADDRESS1],[LOCALADDRESS2]\t\t\t\t\t\t\t\t-2147483648",
112 }, results);
113 }
114
115 [Fact]
116 public void CanBuildWithPropertiesUsingFirewallARM64()
117 {
118 var folder = TestData.Get(@"TestData\UsingProperties");
119 var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder });
120
121 var results = build.BuildAndQuery(BuildARM64, "Wix5FirewallException", "CustomAction");
122 WixAssert.CompareLineByLine(new[]
123 {
124 "CustomAction:Wix5ExecFirewallExceptionsInstall_A64\t3073\tWix5FWCA_A64\tExecFirewallExceptions\t",
125 "CustomAction:Wix5ExecFirewallExceptionsUninstall_A64\t3073\tWix5FWCA_A64\tExecFirewallExceptions\t",
126 "CustomAction:Wix5RollbackFirewallExceptionsInstall_A64\t3329\tWix5FWCA_A64\tExecFirewallExceptions\t",
127 "CustomAction:Wix5RollbackFirewallExceptionsUninstall_A64\t3329\tWix5FWCA_A64\tExecFirewallExceptions\t",
128 "CustomAction:Wix5SchedFirewallExceptionsInstall_A64\t1\tWix5FWCA_A64\tSchedFirewallExceptionsInstall\t",
129 "CustomAction:Wix5SchedFirewallExceptionsUninstall_A64\t1\tWix5FWCA_A64\tSchedFirewallExceptionsUninstall\t",
130 "Wix5FirewallException:fexRrE4bS.DwUJQMvzX0ALEsx7jrZs\tSingle Nested properties\t[REMOTEADDRESS]\t\t-2147483648\t\t0\t-2147483648\tFirewallComponent\t\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t[INTERFACE]\t[INTERFACETYPE]\t[LOCALADDRESS]\t\t\t\t\t\t\t\t-2147483648",
131 "Wix5FirewallException:fexvEy1GfdOjHlKcvsguyqK6mvYKyk\t[NAME]\t[REMOTESCOPE]\t[LOCALPORT]\t[PROTOCOL]\t[PROGRAM]\t16\t[PROFILE]\tFirewallComponent\t[DESCRIPTION]\t1\t[ACTION]\t[EDGETRAVERSAL]\t[ENABLED]\t[GROUPING]\t[ICMPTYPES]\t[INTERFACE]\t[INTERFACETYPE]\t[LOCALSCOPE]\t[REMOTEPORT]\t[SERVICE]\t[PACKAGEID]\t[LOCALUSERS]\t[LOCALOWNER]\t[REMOTEMACHINES]\t[REMOTEUSERS]\t[SECUREFLAGS]",
132 "Wix5FirewallException:fexWywW3VGiEuG23FOv1YM6h7R6F5Q\tMultiple Nested properties\t[REMOTEADDRESS1],[REMOTEADDRESS2]\t\t-2147483648\t\t0\t-2147483648\tFirewallComponent\t\t1\t-2147483648\t-2147483648\t-2147483648\t\t\t[INTERFACE1]|[INTERFACE2]\t[INTERFACETYPE1],[INTERFACETYPE2]\t[LOCALADDRESS1],[LOCALADDRESS2]\t\t\t\t\t\t\t\t-2147483648",
60 }, results); 133 }, results);
61 } 134 }
62 135
@@ -83,6 +156,59 @@ namespace WixToolsetTest.Firewall
83 "FirewallException", 156 "FirewallException",
84 "FirewallException", 157 "FirewallException",
85 "FirewallException", 158 "FirewallException",
159 "FirewallException",
160 "FirewallException",
161 "LocalAddress",
162 "LocalAddress",
163 "FirewallException",
164 "RemoteAddress",
165 "Interface",
166 "Interface",
167 "FirewallException",
168 "FirewallException",
169 "InterfaceType",
170 "InterfaceType",
171 "FirewallException",
172 "FirewallException",
173 "FirewallException",
174 "FirewallException",
175 "FirewallException",
176 "FirewallException",
177 "FirewallException",
178 "FirewallException",
179 "FirewallException",
180 "FirewallException",
181 }, actual.Select(a => a.Name).ToArray());
182 }
183
184 [Fact]
185 public void CanRoundtripFirewallExceptionsWithProperties()
186 {
187 var folder = TestData.Get(@"TestData", "UsingProperties");
188 var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder });
189 var output = Path.Combine(folder, "FirewallPropertiesDecompile.xml");
190
191 build.BuildAndDecompileAndBuild(Build, Decompile, output);
192
193 var doc = XDocument.Load(output);
194 var actual = doc.Descendants()
195 .Where(e => e.Name.Namespace == "http://wixtoolset.org/schemas/v4/wxs/firewall")
196 .Select(fe => new { Name = fe.Name.LocalName, Attributes = fe.Attributes().Select(a => $"{a.Name.LocalName}={a.Value}").ToArray() })
197 .ToArray();
198
199 WixAssert.CompareLineByLine(new[]
200 {
201 "FirewallException",
202 "FirewallException",
203 "FirewallException",
204 "RemoteAddress",
205 "RemoteAddress",
206 "Interface",
207 "Interface",
208 "InterfaceType",
209 "InterfaceType",
210 "LocalAddress",
211 "LocalAddress",
86 }, actual.Select(a => a.Name).ToArray()); 212 }, actual.Select(a => a.Name).ToArray());
87 } 213 }
88 214
@@ -98,9 +224,8 @@ namespace WixToolsetTest.Firewall
98 "Port=42", 224 "Port=42",
99 "Protocol=tcp", 225 "Protocol=tcp",
100 "Program=[#filNdJBJmq3UCUIwmXS8x21aAsvqzk]", 226 "Program=[#filNdJBJmq3UCUIwmXS8x21aAsvqzk]",
101 "Profile=all", 227 "OnUpdate=DoNothing",
102 "Description=An app-based firewall exception", 228 "Description=An app-based firewall exception",
103 "Outbound=no",
104 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall", 229 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
105 }, actual.Attributes); 230 }, actual.Attributes);
106 } 231 }
@@ -111,12 +236,12 @@ namespace WixToolsetTest.Firewall
111 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExamplePort"); 236 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExamplePort");
112 WixAssert.CompareLineByLine(new[] 237 WixAssert.CompareLineByLine(new[]
113 { 238 {
114 "Id=fex70IVsYNnbwiHQrEepmdTPKH8XYs", 239 "Id=fexaUTe2tRRcSYrPUTn44DAZhE.40Q",
115 "Name=ExamplePort", 240 "Name=ExamplePort",
116 "Scope=localSubnet", 241 "Scope=localSubnet",
117 "Port=42", 242 "Port=42",
118 "Protocol=tcp", 243 "Protocol=tcp",
119 "Profile=all", 244 "OnUpdate=EnableOnly",
120 "Description=A port-based firewall exception", 245 "Description=A port-based firewall exception",
121 "Outbound=yes", 246 "Outbound=yes",
122 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall", 247 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
@@ -129,14 +254,12 @@ namespace WixToolsetTest.Firewall
129 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleDNSScope"); 254 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleDNSScope");
130 WixAssert.CompareLineByLine(new[] 255 WixAssert.CompareLineByLine(new[]
131 { 256 {
132 "Id=fexxY71H2ZBkPalv7uid1Yy4qaA_lA", 257 "Id=fex4FeP470wYcFpw.g7fbIKiLnZPzg",
133 "Name=ExampleDNSScope", 258 "Name=ExampleDNSScope",
134 "Scope=DNS", 259 "Scope=DNS",
135 "Port=356", 260 "Port=356",
136 "Protocol=udp", 261 "Protocol=udp",
137 "Profile=all",
138 "Description=DNS scope firewall exception", 262 "Description=DNS scope firewall exception",
139 "Outbound=no",
140 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall", 263 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
141 }, actual.Attributes); 264 }, actual.Attributes);
142 } 265 }
@@ -147,14 +270,13 @@ namespace WixToolsetTest.Firewall
147 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleDHCPScope"); 270 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleDHCPScope");
148 WixAssert.CompareLineByLine(new[] 271 WixAssert.CompareLineByLine(new[]
149 { 272 {
150 "Id=fex6bkfWwpiRGI.wVFx0T7W4LXIHxU", 273 "Id=fexpWUzK53RVnaluW36gSmphPRY8VY",
151 "Name=ExampleDHCPScope", 274 "Name=ExampleDHCPScope",
152 "Scope=DHCP", 275 "Scope=DHCP",
153 "Protocol=211", 276 "Protocol=211",
154 "Program=test.exe", 277 "Program=test.exe",
155 "Profile=public", 278 "Profile=public",
156 "Description=DHCP scope firewall exception", 279 "Description=DHCP scope firewall exception",
157 "Outbound=no",
158 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall" 280 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall"
159 }, actual.Attributes); 281 }, actual.Attributes);
160 } 282 }
@@ -165,14 +287,13 @@ namespace WixToolsetTest.Firewall
165 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleWINSScope"); 287 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleWINSScope");
166 WixAssert.CompareLineByLine(new[] 288 WixAssert.CompareLineByLine(new[]
167 { 289 {
168 "Id=fexXxaXCXXFh.UxO_BjmZxi1B1du_Q", 290 "Id=fexD6w20c5HfNi4l1vHFj_eet4cC8I",
169 "Name=ExampleWINSScope", 291 "Name=ExampleWINSScope",
170 "Scope=WINS", 292 "Scope=WINS",
171 "Port=6573", 293 "Port=6573",
172 "Protocol=tcp", 294 "Protocol=tcp",
173 "Profile=domain", 295 "Profile=domain",
174 "Description=WINS scope firewall exception", 296 "Description=WINS scope firewall exception",
175 "Outbound=no",
176 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall", 297 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
177 }, actual.Attributes); 298 }, actual.Attributes);
178 } 299 }
@@ -183,18 +304,322 @@ namespace WixToolsetTest.Firewall
183 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleDefaultGatewayScope"); 304 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ExampleDefaultGatewayScope");
184 WixAssert.CompareLineByLine(new[] 305 WixAssert.CompareLineByLine(new[]
185 { 306 {
186 "Id=fex_ZpDsnKyHlYiA24JHzvFxm3uLZ8", 307 "Id=fex8vMfBplrod4daEz3PqDTeX6olGE",
187 "Name=ExampleDefaultGatewayScope", 308 "Name=ExampleDefaultGatewayScope",
188 "Scope=defaultGateway", 309 "Scope=defaultGateway",
189 "Port=4432", 310 "Port=4432",
190 "Protocol=tcp", 311 "Protocol=tcp",
191 "Profile=private", 312 "Profile=private",
192 "Description=defaultGateway scope firewall exception", 313 "Description=defaultGateway scope firewall exception",
193 "Outbound=no",
194 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall", 314 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
195 }, actual.Attributes); 315 }, actual.Attributes);
196 } 316 }
197 317
318 [Fact]
319 public void RoundtripAttributesAreCorrectForINetFwRule3Values()
320 {
321 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "INetFwRule3 values");
322 WixAssert.CompareLineByLine(new[]
323 {
324 "Id=fexwjf4OTFVE9SNiC4goVxBA6ENJBE",
325 "Name=INetFwRule3 values",
326 "Scope=any",
327 "Description=Simple INetFwRule3 values",
328 "LocalAppPackageId=S-1-15-2-1239072475-3687740317-1842961305-3395936705-4023953123-1525404051-2779347315",
329 "LocalUserAuthorizedList=O:LSD:(A;;CC;;;S-1-5-84-0-0-0-0-0)",
330 "LocalUserOwner=S-1-5-21-1898747406-2352535518-1247798438-1914",
331 "RemoteMachineAuthorizedList=127.0.0.1",
332 "RemoteUserAuthorizedList=O:LSD:(A;;CC;;;S-1-5-84-0-0-0-0-0)",
333 "IPSecSecureFlags=NegotiateEncryption",
334 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
335 }, actual.Attributes);
336 }
337
338 [Fact]
339 public void RoundtripAttributesAreCorrectForINetFwRule3Properties()
340 {
341 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "INetFwRule3 properties");
342 WixAssert.CompareLineByLine(new[]
343 {
344 "Id=fexAMmHzFDyQmubTOnKS1Cn0Y3q_Ug",
345 "Name=INetFwRule3 properties",
346 "Scope=any",
347 "Description=INetFwRule3 passed via properties",
348 "LocalAppPackageId=[PROP1]",
349 "LocalUserAuthorizedList=[PROP2]",
350 "LocalUserOwner=[PROP3]",
351 "RemoteMachineAuthorizedList=[PROP4]",
352 "RemoteUserAuthorizedList=[PROP5]",
353 "IPSecSecureFlags=[PROP6]",
354 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
355 }, actual.Attributes);
356 }
357
358 [Fact]
359 public void RoundtripAttributesAreCorrectForGroupingValue()
360 {
361 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "GroupingExample1");
362 WixAssert.CompareLineByLine(new[]
363 {
364 "Id=fexfzjTQsWwZkHQpObtl0XaUosfcRk",
365 "Name=GroupingExample1",
366 "Program=fw.exe",
367 "Description=Simple rule with grouping",
368 "Grouping=@yourresources.dll,-1005",
369 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
370 }, actual.Attributes);
371 }
372
373 [Fact]
374 public void RoundtripAttributesAreCorrectForGroupingProperty()
375 {
376 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "GroupingExample2");
377 WixAssert.CompareLineByLine(new[]
378 {
379 "Id=fexVr6uHcOCak5MHuTLwujjh_oKtbI",
380 "Name=GroupingExample2",
381 "Port=8732",
382 "Protocol=tcp",
383 "Description=Rule with grouping property",
384 "Grouping=[GROUPING_PROP]",
385 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
386 }, actual.Attributes);
387 }
388
389 [Fact]
390 public void RoundtripAttributesAreCorrectForIcmpValue()
391 {
392 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ICMPExample1");
393 WixAssert.CompareLineByLine(new[]
394 {
395 "Id=fexEPvcf4iexD1mVQdvxm7tD02nZEc",
396 "Name=ICMPExample1",
397 "Protocol=2",
398 "Description=Simple ICMP rule",
399 "IcmpTypesAndCodes=4:*,9:*,12:*",
400 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
401 }, actual.Attributes);
402 }
403
404 [Fact]
405 public void RoundtripAttributesAreCorrectForIcmpProperty()
406 {
407 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "ICMPExample2");
408 WixAssert.CompareLineByLine(new[]
409 {
410 "Id=fexuanTga5xaaFzr9JsAnUmpCNediw",
411 "Name=ICMPExample2",
412 "Protocol=2",
413 "Description=Rule with ICMP property",
414 "IcmpTypesAndCodes=[ICMP_PROP]",
415 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
416 }, actual.Attributes);
417 }
418
419 [Fact]
420 public void RoundtripAttributesAreCorrectForLocalScopeValue()
421 {
422 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "LocalScopeExample1");
423 WixAssert.CompareLineByLine(new[]
424 {
425 "Id=fex0HTxATWjpC2PCoY6DB7f2D1WaKU",
426 "Name=LocalScopeExample1",
427 "Scope=any",
428 "Description=Simple rule with local scope",
429 "LocalScope=localSubnet",
430 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
431 }, actual.Attributes);
432 }
433
434 [Fact]
435 public void RoundtripAttributesAreCorrectForLocalScopeProperty()
436 {
437 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "LocalScopeExample2");
438 WixAssert.CompareLineByLine(new[]
439 {
440 "Id=fex.BGtyMRGAhxb2hG.49JvWYz7fM0",
441 "Name=LocalScopeExample2",
442 "Scope=any",
443 "Description=Rule with local scope property",
444 "LocalScope=[LOCALSCOPE_PROP]",
445 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
446 }, actual.Attributes);
447 }
448
449 [Fact]
450 public void RoundtripAttributesAreCorrectForRemotePorts()
451 {
452 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "RemotePortExample1");
453 WixAssert.CompareLineByLine(new[]
454 {
455 "Id=fexHx2xbwZYzAi0oYp4YGWevJQs5eM",
456 "Name=RemotePortExample1",
457 "Scope=any",
458 "Protocol=tcp",
459 "Description=Simple rule with remote port",
460 "RemotePort=34560",
461 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
462 }, actual.Attributes);
463 }
464
465 [Fact]
466 public void RoundtripAttributesAreCorrectForRemotePortsProperty()
467 {
468 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "RemotePortExample2");
469 WixAssert.CompareLineByLine(new[]
470 {
471 "Id=fexArlOkFR7CAwVZ2wk8yNdiREydu0",
472 "Name=RemotePortExample2",
473 "Protocol=tcp",
474 "Program=fw.exe",
475 "Description=Rule with remote port property",
476 "RemotePort=[REMOTEPORT_PROP]",
477 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall",
478 }, actual.Attributes);
479 }
480
481 [Fact]
482 public void RoundtripAttributesAreCorrectWhenPropertiesAreUsed()
483 {
484 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "[NAME]", "UsingProperties");
485 WixAssert.CompareLineByLine(new[]
486 {
487 "Id=fexvEy1GfdOjHlKcvsguyqK6mvYKyk",
488 "Name=[NAME]",
489 "Scope=[REMOTESCOPE]",
490 "Port=[LOCALPORT]",
491 "Protocol=[PROTOCOL]",
492 "Program=[PROGRAM]",
493 "Profile=[PROFILE]",
494 "Description=[DESCRIPTION]",
495 "Action=[ACTION]",
496 "EdgeTraversal=[EDGETRAVERSAL]",
497 "Enabled=[ENABLED]",
498 "Grouping=[GROUPING]",
499 "IcmpTypesAndCodes=[ICMPTYPES]",
500 "Interface=[INTERFACE]",
501 "InterfaceType=[INTERFACETYPE]",
502 "LocalScope=[LOCALSCOPE]",
503 "RemotePort=[REMOTEPORT]",
504 "Service=[SERVICE]",
505 "LocalAppPackageId=[PACKAGEID]",
506 "LocalUserAuthorizedList=[LOCALUSERS]",
507 "LocalUserOwner=[LOCALOWNER]",
508 "RemoteMachineAuthorizedList=[REMOTEMACHINES]",
509 "RemoteUserAuthorizedList=[REMOTEUSERS]",
510 "IPSecSecureFlags=[SECUREFLAGS]",
511 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall"
512 }, actual.Attributes);
513
514 var folder = TestData.Get(@"TestData", "UsingProperties");
515 var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder });
516 var output = Path.Combine(folder, $"FirewallNothingNested.xml");
517
518 build.BuildAndDecompileAndBuild(Build, Decompile, output);
519
520 var doc = XDocument.Load(output);
521 var related = doc.Descendants()
522 .Where(e =>
523 {
524 return e.Name.Namespace == "http://wixtoolset.org/schemas/v4/wxs/firewall" &&
525 e.Parent.Attributes().Any(a => a.Name.LocalName == "Name" && a.Value == "[NAME]");
526 });
527
528 var nested = related.Select(e => e.Attributes().Single(a => a.Name.LocalName == "Name").Value);
529 Assert.False(nested.Any());
530 }
531
532 [Fact]
533 public void RoundtripAttributesAreCorrectWhenNestedPropertiesAreUsed()
534 {
535 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "Single Nested properties", "UsingProperties");
536 WixAssert.CompareLineByLine(new[]
537 {
538 "Id=fexRrE4bS.DwUJQMvzX0ALEsx7jrZs",
539 "Name=Single Nested properties",
540 "Scope=[REMOTEADDRESS]",
541 "Interface=[INTERFACE]",
542 "InterfaceType=[INTERFACETYPE]",
543 "LocalScope=[LOCALADDRESS]",
544 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall"
545 }, actual.Attributes);
546
547 var folder = TestData.Get(@"TestData", "UsingProperties");
548 var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder });
549 var output = Path.Combine(folder, $"FirewallSingleNested.xml");
550
551 build.BuildAndDecompileAndBuild(Build, Decompile, output);
552
553 var doc = XDocument.Load(output);
554 var related = doc.Descendants()
555 .Where(e =>
556 {
557 return e.Name.Namespace == "http://wixtoolset.org/schemas/v4/wxs/firewall" &&
558 e.Parent.Attributes().Any(a => a.Name.LocalName == "Name" && a.Value == "Single Nested properties");
559 });
560
561 var nested = related.Select(e => e.Attributes().Single(a => a.Name.LocalName == "Name").Value);
562 Assert.False(nested.Any());
563 }
564
565 [Fact]
566 public void RoundtripAttributesAreCorrectWhenMultipleNestedPropertiesAreUsed()
567 {
568 var actual = BuildAndDecompileAndBuild("http://wixtoolset.org/schemas/v4/wxs/firewall", "Multiple Nested properties", "UsingProperties");
569 WixAssert.CompareLineByLine(new[]
570 {
571 "Id=fexWywW3VGiEuG23FOv1YM6h7R6F5Q",
572 "Name=Multiple Nested properties",
573 "xmlns=http://wixtoolset.org/schemas/v4/wxs/firewall"
574 }, actual.Attributes);
575
576 var folder = TestData.Get(@"TestData", "UsingProperties");
577 var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder });
578 var output = Path.Combine(folder, $"FirewallMultipleNested.xml");
579
580 build.BuildAndDecompileAndBuild(Build, Decompile, output);
581
582 var doc = XDocument.Load(output);
583 var related = doc.Descendants()
584 .Where(e =>
585 {
586 return e.Name.Namespace == "http://wixtoolset.org/schemas/v4/wxs/firewall" &&
587 e.Parent.Attributes().Any(a => a.Name.LocalName == "Name" && a.Value == "Multiple Nested properties");
588 });
589
590 var interfaces = related.Where(e => e.Name.LocalName == "Interface")
591 .Select(e => e.Attributes().Single(a => a.Name.LocalName == "Name").Value);
592 WixAssert.CompareLineByLine(new[]
593 {
594 "[INTERFACE1]",
595 "[INTERFACE2]",
596 }, interfaces.ToArray());
597
598 var interfaceTypes = related.Where(e => e.Name.LocalName == "InterfaceType")
599 .Select(e => e.Attributes().Single(a => a.Name.LocalName == "Value").Value);
600 WixAssert.CompareLineByLine(new[]
601 {
602 "[INTERFACETYPE1]",
603 "[INTERFACETYPE2]",
604 }, interfaceTypes.ToArray());
605
606 var remotes = related.Where(e => e.Name.LocalName == "RemoteAddress")
607 .Select(e => e.Attributes().Single(a => a.Name.LocalName == "Value").Value);
608 WixAssert.CompareLineByLine(new[]
609 {
610 "[REMOTEADDRESS1]",
611 "[REMOTEADDRESS2]",
612 }, remotes.ToArray());
613
614 var locals = related.Where(e => e.Name.LocalName == "LocalAddress")
615 .Select(e => e.Attributes().Single(a => a.Name.LocalName == "Value").Value);
616 WixAssert.CompareLineByLine(new[]
617 {
618 "[LOCALADDRESS1]",
619 "[LOCALADDRESS2]",
620 }, locals.ToArray());
621 }
622
198 private static void Build(string[] args) 623 private static void Build(string[] args)
199 { 624 {
200 var result = WixRunner.Execute(args); 625 var result = WixRunner.Execute(args);
@@ -216,15 +641,16 @@ namespace WixToolsetTest.Firewall
216 var result = WixRunner.Execute(args); 641 var result = WixRunner.Execute(args);
217 result.AssertSuccess(); 642 result.AssertSuccess();
218 } 643 }
644
219 class AttributeVerifier 645 class AttributeVerifier
220 { 646 {
221 public string Name { get; set; } 647 public string Name { get; set; }
222 public string[] Attributes { get; set; } 648 public string[] Attributes { get; set; }
223 } 649 }
224 650
225 private static AttributeVerifier BuildAndDecompileAndBuild(string nameSpace, string ruleName) 651 private static AttributeVerifier BuildAndDecompileAndBuild(string nameSpace, string ruleName, string path = "UsingFirewall")
226 { 652 {
227 var folder = TestData.Get(@"TestData", "UsingFirewall"); 653 var folder = TestData.Get(@"TestData", path);
228 var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder }); 654 var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder });
229 var output = Path.Combine(folder, $"Firewall{ruleName}.xml"); 655 var output = Path.Combine(folder, $"Firewall{ruleName}.xml");
230 656
@@ -232,7 +658,10 @@ namespace WixToolsetTest.Firewall
232 658
233 var doc = XDocument.Load(output); 659 var doc = XDocument.Load(output);
234 var actual = doc.Descendants() 660 var actual = doc.Descendants()
235 .Where(e => e.Name.Namespace == nameSpace) 661 .Where(e =>
662 {
663 return e.Name.Namespace == nameSpace && e.Name.LocalName == "FirewallException";
664 })
236 .Select(fe => new AttributeVerifier 665 .Select(fe => new AttributeVerifier
237 { 666 {
238 Name = fe.Attributes().Single(a => a.Name.LocalName == "Name").Value, 667 Name = fe.Attributes().Single(a => a.Name.LocalName == "Name").Value,
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 957aa642..4bb2e192 100644
--- a/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/PackageComponents.wxs
+++ b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/PackageComponents.wxs
@@ -6,16 +6,51 @@
6 <Component> 6 <Component>
7 <File Name="fw.exe" Source="example.txt"> 7 <File Name="fw.exe" Source="example.txt">
8 <Shortcut Id="FwShortcut" Directory="INSTALLFOLDER" Name="Firewall" /> 8 <Shortcut Id="FwShortcut" Directory="INSTALLFOLDER" Name="Firewall" />
9 <fw:FirewallException Id="ExampleFirewall" Description="An app-based firewall exception" Name="ExampleApp" Port="42"> 9 <fw:FirewallException Id="ExampleFirewall" Description="An app-based firewall exception" Name="ExampleApp" Port="42" OnUpdate="DoNothing" >
10 <fw:RemoteAddress Value="*" /> 10 <fw:RemoteAddress Value="*" />
11 </fw:FirewallException> 11 </fw:FirewallException>
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" OnUpdate="EnableOnly" />
15 <fw:FirewallException Description="DNS scope firewall exception" Name="ExampleDNSScope" Port="356" Protocol="udp" Scope="DNS" /> 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" /> 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"/> 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" /> 18 <fw:FirewallException Description="defaultGateway scope firewall exception" Name="ExampleDefaultGatewayScope" Port="4432" Scope="defaultGateway" Profile="private" />
19
20 <fw:FirewallException Description="Defer to user edge traversal" Name="defertouser" Program="fw.exe" EdgeTraversal="DeferToUser" />
21 <fw:FirewallException Description="A port-based service exception" Name="ExampleService" Port="12000" Service="ftpsrv" Program="%windir%\system32\svchost.exe" >
22 <fw:LocalAddress Value="DHCP"/>
23 <fw:LocalAddress Value="WINS"/>
24 </fw:FirewallException>
25
26 <fw:FirewallException Description="Interfaces with nested elements" Name="interface nested" Port="54671" >
27 <fw:RemoteAddress Value="127.0.0.1"/>
28 <fw:Interface Name="Wi-Fi" />
29 <fw:Interface Name="Local Area Connection" />
30 </fw:FirewallException>
31 <fw:FirewallException Description="Interfaces with property" Name="interface property" Port="54671" Interface="[INTERFACE_PROPERTY]" />
32
33 <ServiceInstall Name="svc1" Type="ownProcess" Start="disabled" ErrorControl="ignore" >
34 <fw:FirewallException Id="ServiceInstall.nested" IgnoreFailure="true" Description="A port-based firewall exception for a windows service" Name="ExampleNestedService" Port="3546-7890" Scope="localSubnet" >
35 <fw:InterfaceType Value="Lan" />
36 <fw:InterfaceType Value="Wireless" />
37 </fw:FirewallException>
38 </ServiceInstall>
39
40 <fw:FirewallException Description="Simple INetFwRule3 values" Name="INetFwRule3 values" Scope="any" LocalAppPackageId="S-1-15-2-1239072475-3687740317-1842961305-3395936705-4023953123-1525404051-2779347315" LocalUserAuthorizedList="O:LSD:(A;;CC;;;S-1-5-84-0-0-0-0-0)" LocalUserOwner="S-1-5-21-1898747406-2352535518-1247798438-1914" RemoteMachineAuthorizedList="127.0.0.1" RemoteUserAuthorizedList="O:LSD:(A;;CC;;;S-1-5-84-0-0-0-0-0)" IPSecSecureFlags="NegotiateEncryption" />
41 <fw:FirewallException Description="INetFwRule3 passed via properties" Name="INetFwRule3 properties" Scope="any" LocalAppPackageId="[PROP1]" LocalUserAuthorizedList="[PROP2]" LocalUserOwner="[PROP3]" RemoteMachineAuthorizedList="[PROP4]" RemoteUserAuthorizedList="[PROP5]" IPSecSecureFlags="[PROP6]" />
42
43 <fw:FirewallException Description="Simple rule with grouping" Name="GroupingExample1" Program="fw.exe" Grouping="@yourresources.dll,-1005" />
44 <fw:FirewallException Description="Rule with grouping property" Name="GroupingExample2" Port="8732" Grouping="[GROUPING_PROP]" />
45
46 <fw:FirewallException Description="Simple ICMP rule" Name="ICMPExample1" Protocol="2" IcmpTypesAndCodes="4:*,9:*,12:*" />
47 <fw:FirewallException Description="Rule with ICMP property" Name="ICMPExample2" Protocol="2" IcmpTypesAndCodes="[ICMP_PROP]" />
48
49 <fw:FirewallException Description="Simple rule with local scope" Name="LocalScopeExample1" Scope="any" LocalScope="localSubnet" />
50 <fw:FirewallException Description="Rule with local scope property" Name="LocalScopeExample2" Scope="any" LocalScope="[LOCALSCOPE_PROP]" />
51
52 <fw:FirewallException Description="Simple rule with remote port" Name="RemotePortExample1" Scope="any" RemotePort="34560" />
53 <fw:FirewallException Description="Rule with remote port property" Name="RemotePortExample2" Program="fw.exe" RemotePort="[REMOTEPORT_PROP]" />
19 </Component> 54 </Component>
20 </ComponentGroup> 55 </ComponentGroup>
21 </Fragment> 56 </Fragment>
diff --git a/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingProperties/Package.en-us.wxl b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingProperties/Package.en-us.wxl
new file mode 100644
index 00000000..f1df1234
--- /dev/null
+++ b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingProperties/Package.en-us.wxl
@@ -0,0 +1,9 @@
1<!--
2This file contains the declaration of all the localizable strings.
3-->
4<WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" Culture="en-US">
5
6 <String Id="DowngradeError" Value="A newer version of [ProductName] is already installed." />
7 <String Id="FeatureTitle" Value="MsiPackage" />
8
9</WixLocalization>
diff --git a/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingProperties/Package.wxs b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingProperties/Package.wxs
new file mode 100644
index 00000000..814becd1
--- /dev/null
+++ b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingProperties/Package.wxs
@@ -0,0 +1,15 @@
1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 <Package Name="MsiPackage" Language="1033" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="BB4E61B3-EBE5-4DE7-B3E0-8699B5901D2E">
3 <MajorUpgrade DowngradeErrorMessage="!(loc.DowngradeError)" />
4
5 <Feature Id="ProductFeature" Title="!(loc.FeatureTitle)">
6 <ComponentGroupRef Id="ProductComponents" />
7 </Feature>
8 </Package>
9
10 <Fragment>
11 <StandardDirectory Id="ProgramFilesFolder">
12 <Directory Id="INSTALLFOLDER" Name="MsiPackage" />
13 </StandardDirectory>
14 </Fragment>
15</Wix>
diff --git a/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingProperties/PackageComponents.wxs b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingProperties/PackageComponents.wxs
new file mode 100644
index 00000000..05c3ea8a
--- /dev/null
+++ b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingProperties/PackageComponents.wxs
@@ -0,0 +1,53 @@
1<?xml version="1.0" encoding="utf-8"?>
2<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
3 xmlns:fw="http://wixtoolset.org/schemas/v4/wxs/firewall">
4 <Fragment>
5 <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
6 <Component Id="FirewallComponent" Guid="28DF3387-F30E-4DBE-90E2-D2C760CB4DD9">
7 <fw:FirewallException
8 Name="[NAME]"
9 Port="[LOCALPORT]"
10 Protocol="[PROTOCOL]"
11 Program="[PROGRAM]"
12 Profile="[PROFILE]"
13 Description="[DESCRIPTION]"
14 Scope="[REMOTESCOPE]"
15 Action="[ACTION]"
16 EdgeTraversal="[EDGETRAVERSAL]"
17 Enabled="[ENABLED]"
18 Grouping="[GROUPING]"
19 IcmpTypesAndCodes="[ICMPTYPES]"
20 Interface="[INTERFACE]"
21 InterfaceType="[INTERFACETYPE]"
22 LocalScope="[LOCALSCOPE]"
23 RemotePort="[REMOTEPORT]"
24 Service="[SERVICE]"
25 LocalAppPackageId="[PACKAGEID]"
26 LocalUserAuthorizedList="[LOCALUSERS]"
27 LocalUserOwner="[LOCALOWNER]"
28 RemoteMachineAuthorizedList="[REMOTEMACHINES]"
29 RemoteUserAuthorizedList="[REMOTEUSERS]"
30 IPSecSecureFlags="[SECUREFLAGS]"
31 />
32
33 <fw:FirewallException Name="Single Nested properties" >
34 <fw:RemoteAddress Value="[REMOTEADDRESS]" />
35 <fw:LocalAddress Value="[LOCALADDRESS]" />
36 <fw:InterfaceType Value="[INTERFACETYPE]" />
37 <fw:Interface Name="[INTERFACE]" />
38 </fw:FirewallException>
39
40 <fw:FirewallException Name="Multiple Nested properties" >
41 <fw:RemoteAddress Value="[REMOTEADDRESS1]" />
42 <fw:RemoteAddress Value="[REMOTEADDRESS2]" />
43 <fw:LocalAddress Value="[LOCALADDRESS1]" />
44 <fw:LocalAddress Value="[LOCALADDRESS2]" />
45 <fw:InterfaceType Value="[INTERFACETYPE1]" />
46 <fw:InterfaceType Value="[INTERFACETYPE2]" />
47 <fw:Interface Name="[INTERFACE1]" />
48 <fw:Interface Name="[INTERFACE2]" />
49 </fw:FirewallException>
50 </Component>
51 </ComponentGroup>
52 </Fragment>
53</Wix>
diff --git a/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingProperties/example.txt b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingProperties/example.txt
new file mode 100644
index 00000000..1b4ffe8a
--- /dev/null
+++ b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingProperties/example.txt
@@ -0,0 +1 @@
This is example.txt. \ No newline at end of file
diff --git a/src/ext/Firewall/test/WixToolsetTest.Firewall/WixToolsetTest.Firewall.csproj b/src/ext/Firewall/test/WixToolsetTest.Firewall/WixToolsetTest.Firewall.csproj
index e46020a6..68acfe52 100644
--- a/src/ext/Firewall/test/WixToolsetTest.Firewall/WixToolsetTest.Firewall.csproj
+++ b/src/ext/Firewall/test/WixToolsetTest.Firewall/WixToolsetTest.Firewall.csproj
@@ -5,6 +5,8 @@
5 <PropertyGroup> 5 <PropertyGroup>
6 <TargetFramework>net6.0</TargetFramework> 6 <TargetFramework>net6.0</TargetFramework>
7 <IsWixTestProject>true</IsWixTestProject> 7 <IsWixTestProject>true</IsWixTestProject>
8 <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
9 <GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
8 </PropertyGroup> 10 </PropertyGroup>
9 11
10 <ItemGroup> 12 <ItemGroup>
diff --git a/src/ext/Firewall/wixext/FirewallCompiler.cs b/src/ext/Firewall/wixext/FirewallCompiler.cs
index ed49ba9c..c4a5318c 100644
--- a/src/ext/Firewall/wixext/FirewallCompiler.cs
+++ b/src/ext/Firewall/wixext/FirewallCompiler.cs
@@ -35,7 +35,7 @@ namespace WixToolset.Firewall
35 switch (element.Name.LocalName) 35 switch (element.Name.LocalName)
36 { 36 {
37 case "FirewallException": 37 case "FirewallException":
38 this.ParseFirewallExceptionElement(intermediate, section, element, fileComponentId, fileId); 38 this.ParseFirewallExceptionElement(intermediate, section, parentElement, element, fileComponentId, fileId, null);
39 break; 39 break;
40 default: 40 default:
41 this.ParseHelper.UnexpectedElement(parentElement, element); 41 this.ParseHelper.UnexpectedElement(parentElement, element);
@@ -48,7 +48,35 @@ namespace WixToolset.Firewall
48 switch (element.Name.LocalName) 48 switch (element.Name.LocalName)
49 { 49 {
50 case "FirewallException": 50 case "FirewallException":
51 this.ParseFirewallExceptionElement(intermediate, section, element, componentId, null); 51 this.ParseFirewallExceptionElement(intermediate, section, parentElement, element, componentId, null, null);
52 break;
53 default:
54 this.ParseHelper.UnexpectedElement(parentElement, element);
55 break;
56 }
57 break;
58 case "ServiceConfig":
59 var serviceConfigName = context["ServiceConfigServiceName"];
60 var serviceConfigComponentId = context["ServiceConfigComponentId"];
61
62 switch (element.Name.LocalName)
63 {
64 case "FirewallException":
65 this.ParseFirewallExceptionElement(intermediate, section, parentElement, element, serviceConfigComponentId, null, serviceConfigName);
66 break;
67 default:
68 this.ParseHelper.UnexpectedElement(parentElement, element);
69 break;
70 }
71 break;
72 case "ServiceInstall":
73 var serviceInstallName = context["ServiceInstallName"];
74 var serviceInstallComponentId = context["ServiceInstallComponentId"];
75
76 switch (element.Name.LocalName)
77 {
78 case "FirewallException":
79 this.ParseFirewallExceptionElement(intermediate, section, parentElement, element, serviceInstallComponentId, null, serviceInstallName);
52 break; 80 break;
53 default: 81 default:
54 this.ParseHelper.UnexpectedElement(parentElement, element); 82 this.ParseHelper.UnexpectedElement(parentElement, element);
@@ -64,10 +92,12 @@ namespace WixToolset.Firewall
64 /// <summary> 92 /// <summary>
65 /// Parses a FirewallException element. 93 /// Parses a FirewallException element.
66 /// </summary> 94 /// </summary>
95 /// <param name="parentElement">The parent element of the one being parsed.</param>
67 /// <param name="element">The element to parse.</param> 96 /// <param name="element">The element to parse.</param>
68 /// <param name="componentId">Identifier of the component that owns this firewall exception.</param> 97 /// <param name="componentId">Identifier of the component that owns this firewall exception.</param>
69 /// <param name="fileId">The file identifier of the parent element (null if nested under Component).</param> 98 /// <param name="fileId">The file identifier of the parent element (null if nested under Component).</param>
70 private void ParseFirewallExceptionElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string fileId) 99 /// <param name="serviceName">The service name of the parent element (null if not nested under ServiceConfig or ServiceInstall).</param>
100 private void ParseFirewallExceptionElement(Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, string componentId, string fileId, string serviceName)
71 { 101 {
72 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); 102 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
73 Identifier id = null; 103 Identifier id = null;
@@ -76,12 +106,32 @@ namespace WixToolset.Firewall
76 string file = null; 106 string file = null;
77 string program = null; 107 string program = null;
78 string port = null; 108 string port = null;
79 int? protocol = null; 109 string protocol = null;
80 int? profile = null; 110 string profile = null;
81 string scope = null; 111 string scope = null;
82 string remoteAddresses = null; 112 string remoteAddresses = null;
83 string description = null; 113 string description = null;
84 int? direction = null; 114 int? direction = null;
115 string protocolValue = null;
116 string action = null;
117 string edgeTraversal = null;
118 string enabled = null;
119 string grouping = null;
120 string icmpTypesAndCodes = null;
121 string interfaces = null;
122 string interfaceValue = null;
123 string interfaceTypes = null;
124 string interfaceTypeValue = null;
125 string localScope = null;
126 string localAddresses = null;
127 string remotePort = null;
128 string service = null;
129 string localAppPackageId = null;
130 string localUserAuthorizedList = null;
131 string localUserOwner = null;
132 string remoteMachineAuthorizedList = null;
133 string remoteUserAuthorizedList = null;
134 string secureFlags = null;
85 135
86 foreach (var attrib in element.Attributes()) 136 foreach (var attrib in element.Attributes())
87 { 137 {
@@ -96,9 +146,9 @@ namespace WixToolset.Firewall
96 name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); 146 name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
97 break; 147 break;
98 case "File": 148 case "File":
99 if (null != fileId) 149 if (fileId != null)
100 { 150 {
101 this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, "File", "File")); 151 this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, "File", parentElement.Name.LocalName));
102 } 152 }
103 else 153 else
104 { 154 {
@@ -106,15 +156,31 @@ namespace WixToolset.Firewall
106 } 156 }
107 break; 157 break;
108 case "IgnoreFailure": 158 case "IgnoreFailure":
109 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) 159 if (this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib) == YesNoType.Yes)
110 { 160 {
111 attributes |= 0x1; // feaIgnoreFailures 161 attributes |= 0x1; // feaIgnoreFailures
112 } 162 }
113 break; 163 break;
164 case "OnUpdate":
165 var onupdate = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
166 switch (onupdate)
167 {
168 case "DoNothing":
169 attributes |= 0x2; // feaIgnoreUpdates
170 break;
171 case "EnableOnly":
172 attributes |= 0x4; // feaEnableOnUpdate
173 break;
174
175 default:
176 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "OnUpdate", onupdate, "EnableOnly", "DoNothing"));
177 break;
178 }
179 break;
114 case "Program": 180 case "Program":
115 if (null != fileId) 181 if (fileId != null)
116 { 182 {
117 this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, "Program", "File")); 183 this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, "Program", parentElement.Name.LocalName));
118 } 184 }
119 else 185 else
120 { 186 {
@@ -125,22 +191,28 @@ namespace WixToolset.Firewall
125 port = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); 191 port = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
126 break; 192 break;
127 case "Protocol": 193 case "Protocol":
128 var protocolValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); 194 protocolValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
129 switch (protocolValue) 195 switch (protocolValue)
130 { 196 {
197 case FirewallConstants.IntegerNotSetString:
198 break;
199
131 case "tcp": 200 case "tcp":
132 protocol = FirewallConstants.NET_FW_IP_PROTOCOL_TCP; 201 protocol = FirewallConstants.NET_FW_IP_PROTOCOL_TCP.ToString();
133 break; 202 break;
134 case "udp": 203 case "udp":
135 protocol = FirewallConstants.NET_FW_IP_PROTOCOL_UDP; 204 protocol = FirewallConstants.NET_FW_IP_PROTOCOL_UDP.ToString();
136 break; 205 break;
206
137 default: 207 default:
138 int parsedProtocol; 208 protocol = protocolValue;
139 if (!Int32.TryParse(protocolValue, out parsedProtocol) || parsedProtocol > 255 || parsedProtocol < 0) 209 if (!this.ParseHelper.ContainsProperty(protocolValue))
140 { 210 {
141 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Protocol", protocolValue, "tcp", "udp", "0-255")); 211 if (!Int32.TryParse(protocolValue, out var parsedProtocol) || parsedProtocol > 255 || parsedProtocol < 0)
212 {
213 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Protocol", protocolValue, "tcp", "udp", "0-255"));
214 }
142 } 215 }
143 protocol = parsedProtocol;
144 break; 216 break;
145 } 217 }
146 break; 218 break;
@@ -167,7 +239,11 @@ namespace WixToolset.Firewall
167 remoteAddresses = "DefaultGateway"; 239 remoteAddresses = "DefaultGateway";
168 break; 240 break;
169 default: 241 default:
170 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Scope", scope, "any", "localSubnet", "DNS", "DHCP", "WINS", "defaultGateway")); 242 remoteAddresses = scope;
243 if (!this.ParseHelper.ContainsProperty(scope))
244 {
245 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Scope", scope, "any", "localSubnet", "DNS", "DHCP", "WINS", "defaultGateway"));
246 }
171 break; 247 break;
172 } 248 }
173 break; 249 break;
@@ -176,19 +252,23 @@ namespace WixToolset.Firewall
176 switch (profileValue) 252 switch (profileValue)
177 { 253 {
178 case "domain": 254 case "domain":
179 profile = FirewallConstants.NET_FW_PROFILE2_DOMAIN; 255 profile = FirewallConstants.NET_FW_PROFILE2_DOMAIN.ToString();
180 break; 256 break;
181 case "private": 257 case "private":
182 profile = FirewallConstants.NET_FW_PROFILE2_PRIVATE; 258 profile = FirewallConstants.NET_FW_PROFILE2_PRIVATE.ToString();
183 break; 259 break;
184 case "public": 260 case "public":
185 profile = FirewallConstants.NET_FW_PROFILE2_PUBLIC; 261 profile = FirewallConstants.NET_FW_PROFILE2_PUBLIC.ToString();
186 break; 262 break;
187 case "all": 263 case "all":
188 profile = FirewallConstants.NET_FW_PROFILE2_ALL; 264 profile = FirewallConstants.NET_FW_PROFILE2_ALL.ToString();
189 break; 265 break;
190 default: 266 default:
191 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Profile", profileValue, "domain", "private", "public", "all")); 267 profile = profileValue;
268 if (!this.ParseHelper.ContainsProperty(profileValue))
269 {
270 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Profile", profileValue, "domain", "private", "public", "all"));
271 }
192 break; 272 break;
193 } 273 }
194 break; 274 break;
@@ -200,6 +280,196 @@ namespace WixToolset.Firewall
200 ? FirewallConstants.NET_FW_RULE_DIR_OUT 280 ? FirewallConstants.NET_FW_RULE_DIR_OUT
201 : FirewallConstants.NET_FW_RULE_DIR_IN; 281 : FirewallConstants.NET_FW_RULE_DIR_IN;
202 break; 282 break;
283 case "Action":
284 action = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
285 switch (action)
286 {
287 case "Block":
288 action = "0";
289 break;
290 case "Allow":
291 action = "1";
292 break;
293
294 default:
295 if (!this.ParseHelper.ContainsProperty(action))
296 {
297 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Action", action, "Allow", "Block"));
298 }
299 break;
300 }
301 break;
302 case "EdgeTraversal":
303 edgeTraversal = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
304 switch (edgeTraversal)
305 {
306 case "Deny":
307 edgeTraversal = FirewallConstants.NET_FW_EDGE_TRAVERSAL_TYPE_DENY.ToString();
308 break;
309 case "Allow":
310 edgeTraversal = FirewallConstants.NET_FW_EDGE_TRAVERSAL_TYPE_ALLOW.ToString();
311 break;
312 case "DeferToApp":
313 attributes |= 0x8; // feaAddINetFwRule2
314 edgeTraversal = FirewallConstants.NET_FW_EDGE_TRAVERSAL_TYPE_DEFER_TO_APP.ToString();
315 break;
316 case "DeferToUser":
317 attributes |= 0x8; // feaAddINetFwRule2
318 edgeTraversal = FirewallConstants.NET_FW_EDGE_TRAVERSAL_TYPE_DEFER_TO_USER.ToString();
319 break;
320
321 default:
322 if (!this.ParseHelper.ContainsProperty(edgeTraversal))
323 {
324 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "EdgeTraversal", edgeTraversal, "Allow", "DeferToApp", "DeferToUser", "Deny"));
325 }
326 break;
327 }
328 break;
329 case "Enabled":
330 enabled = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
331 if (!this.ParseHelper.ContainsProperty(enabled))
332 {
333 switch (this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
334 {
335 case YesNoType.Yes:
336 enabled = "1";
337 break;
338 case YesNoType.No:
339 enabled = "0";
340 break;
341
342 default:
343 this.Messaging.Write(ErrorMessages.IllegalYesNoValue(sourceLineNumbers, element.Name.LocalName, "Enabled", enabled));
344 break;
345 }
346 }
347 break;
348 case "Grouping":
349 grouping = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
350 break;
351 case "IcmpTypesAndCodes":
352 icmpTypesAndCodes = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
353 break;
354 case "Interface":
355 interfaceValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
356 interfaces = interfaceValue;
357 break;
358 case "InterfaceType":
359 interfaceTypeValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
360 switch (interfaceTypeValue)
361 {
362 case "RemoteAccess":
363 case "Wireless":
364 case "Lan":
365 case "All":
366 break;
367
368 default:
369 if (!this.ParseHelper.ContainsProperty(interfaceTypeValue))
370 {
371 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "InterfaceType", interfaceTypeValue, "RemoteAccess", "Wireless", "Lan", "All"));
372 }
373 break;
374 }
375 interfaceTypes = interfaceTypeValue;
376 break;
377 case "LocalScope":
378 localScope = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
379 switch (localScope)
380 {
381 case "any":
382 localAddresses = "*";
383 break;
384 case "localSubnet":
385 localAddresses = "LocalSubnet";
386 break;
387 case "DNS":
388 localAddresses = "dns";
389 break;
390 case "DHCP":
391 localAddresses = "dhcp";
392 break;
393 case "WINS":
394 localAddresses = "wins";
395 break;
396 case "defaultGateway":
397 localAddresses = "DefaultGateway";
398 break;
399
400 default:
401 if (!this.ParseHelper.ContainsProperty(localScope))
402 {
403 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "LocalScope", localScope, "any", "localSubnet", "DNS", "DHCP", "WINS", "defaultGateway"));
404 }
405 else
406 {
407 localAddresses = localScope;
408 }
409 break;
410 }
411 break;
412 case "RemotePort":
413 remotePort = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
414 break;
415 case "Service":
416 if (serviceName != null)
417 {
418 this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, "Service", parentElement.Name.LocalName));
419 }
420 else
421 {
422 service = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
423 }
424 break;
425 case "LocalAppPackageId":
426 localAppPackageId = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
427 attributes |= 0x10; // feaAddINetFwRule3
428 break;
429 case "LocalUserAuthorizedList":
430 localUserAuthorizedList = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
431 attributes |= 0x10; // feaAddINetFwRule3
432 break;
433 case "LocalUserOwner":
434 localUserOwner = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
435 attributes |= 0x10; // feaAddINetFwRule3
436 break;
437 case "RemoteMachineAuthorizedList":
438 remoteMachineAuthorizedList = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
439 attributes |= 0x10; // feaAddINetFwRule3
440 break;
441 case "RemoteUserAuthorizedList":
442 remoteUserAuthorizedList = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
443 attributes |= 0x10; // feaAddINetFwRule3
444 break;
445 case "IPSecSecureFlags":
446 secureFlags = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
447 attributes |= 0x10; // feaAddINetFwRule3
448 if (!this.ParseHelper.ContainsProperty(secureFlags))
449 {
450 switch (secureFlags)
451 {
452 case "None":
453 secureFlags = "0";
454 break;
455 case "NoEncapsulation":
456 secureFlags = "1";
457 break;
458 case "WithIntegrity":
459 secureFlags = "2";
460 break;
461 case "NegotiateEncryption":
462 secureFlags = "3";
463 break;
464 case "Encrypt":
465 secureFlags = "4";
466 break;
467 default:
468 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "IPSecSecureFlags", secureFlags, "None", "NoEncapsulation", "WithIntegrity", "NegotiateEncryption", "Encrypt"));
469 break;
470 }
471 }
472 break;
203 default: 473 default:
204 this.ParseHelper.UnexpectedAttribute(element, attrib); 474 this.ParseHelper.UnexpectedAttribute(element, attrib);
205 break; 475 break;
@@ -211,7 +481,7 @@ namespace WixToolset.Firewall
211 } 481 }
212 } 482 }
213 483
214 // parse RemoteAddress children 484 // parse children
215 foreach (var child in element.Elements()) 485 foreach (var child in element.Elements())
216 { 486 {
217 if (this.Namespace == child.Name.Namespace) 487 if (this.Namespace == child.Name.Namespace)
@@ -219,7 +489,7 @@ namespace WixToolset.Firewall
219 switch (child.Name.LocalName) 489 switch (child.Name.LocalName)
220 { 490 {
221 case "RemoteAddress": 491 case "RemoteAddress":
222 if (null != scope) 492 if (scope != null)
223 { 493 {
224 this.Messaging.Write(FirewallErrors.IllegalRemoteAddressWithScopeAttribute(sourceLineNumbers)); 494 this.Messaging.Write(FirewallErrors.IllegalRemoteAddressWithScopeAttribute(sourceLineNumbers));
225 } 495 }
@@ -228,6 +498,37 @@ namespace WixToolset.Firewall
228 this.ParseRemoteAddressElement(intermediate, section, child, ref remoteAddresses); 498 this.ParseRemoteAddressElement(intermediate, section, child, ref remoteAddresses);
229 } 499 }
230 break; 500 break;
501 case "Interface":
502 if (interfaceValue != null)
503 {
504 this.Messaging.Write(FirewallErrors.IllegalInterfaceWithInterfaceAttribute(sourceLineNumbers));
505 }
506 else
507 {
508 this.ParseInterfaceElement(intermediate, section, child, ref interfaces);
509 }
510 break;
511 case "InterfaceType":
512 if (interfaceTypeValue != null)
513 {
514 this.Messaging.Write(FirewallErrors.IllegalInterfaceTypeWithInterfaceTypeAttribute(sourceLineNumbers));
515 }
516 else
517 {
518 this.ParseInterfaceTypeElement(intermediate, section, child, ref interfaceTypes);
519 }
520 break;
521 case "LocalAddress":
522 if (localScope != null)
523 {
524 this.Messaging.Write(FirewallErrors.IllegalLocalAddressWithLocalScopeAttribute(sourceLineNumbers));
525 }
526 else
527 {
528 this.ParseLocalAddressElement(intermediate, section, child, ref localAddresses);
529 }
530 break;
531
231 default: 532 default:
232 this.ParseHelper.UnexpectedElement(element, child); 533 this.ParseHelper.UnexpectedElement(element, child);
233 break; 534 break;
@@ -239,54 +540,84 @@ namespace WixToolset.Firewall
239 } 540 }
240 } 541 }
241 542
242 if (null == id) 543 if (id == null)
243 { 544 {
244 id = this.ParseHelper.CreateIdentifier("fex", name, remoteAddresses, componentId); 545 // firewall rule names are meant to be unique
546 id = this.ParseHelper.CreateIdentifier("fex", name, componentId);
245 } 547 }
246 548
247 // Name is required 549 // Name is required
248 if (null == name) 550 if (name == null)
249 { 551 {
250 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name")); 552 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
251 } 553 }
252 554
253 // Scope or child RemoteAddress(es) are required 555 if (service == null)
254 if (null == remoteAddresses)
255 { 556 {
256 this.Messaging.Write(ErrorMessages.ExpectedAttributeOrElement(sourceLineNumbers, element.Name.LocalName, "Scope", "RemoteAddress")); 557 service = serviceName;
257 } 558 }
258 559
259 // can't have both Program and File 560 // can't have both Program and File
260 if (null != program && null != file) 561 if (program != null && file != null)
261 { 562 {
262 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "File", "Program")); 563 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "File", "Program"));
263 } 564 }
264 565
265 // must be nested under File, have File or Program attributes, or have Port attribute 566 // Defer to user edge traversal setting can only be used in a firewall rule where program path and TCP/UDP protocol are specified with no additional conditions.
266 if (String.IsNullOrEmpty(fileId) && String.IsNullOrEmpty(file) && String.IsNullOrEmpty(program) && String.IsNullOrEmpty(port)) 567 if (edgeTraversal == FirewallConstants.NET_FW_EDGE_TRAVERSAL_TYPE_DEFER_TO_USER.ToString())
267 { 568 {
268 this.Messaging.Write(FirewallErrors.NoExceptionSpecified(sourceLineNumbers)); 569 if (protocol != null && !(protocol == FirewallConstants.NET_FW_IP_PROTOCOL_TCP.ToString() || protocol == FirewallConstants.NET_FW_IP_PROTOCOL_UDP.ToString()))
269 } 570 {
571 this.Messaging.Write(ErrorMessages.IllegalAttributeValueWithLegalList(sourceLineNumbers, element.Name.LocalName, "Protocol", protocolValue, "tcp,udp"));
572 }
270 573
271 // Ports can only be specified if the protocol is TCP or UDP. 574 if (String.IsNullOrEmpty(fileId) && String.IsNullOrEmpty(file) && String.IsNullOrEmpty(program))
272 if (!String.IsNullOrEmpty(port) && protocol.HasValue)
273 {
274 switch(protocol.Value)
275 { 575 {
276 case FirewallConstants.NET_FW_IP_PROTOCOL_TCP: 576 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Program", "EdgeTraversal", "DeferToUser"));
277 case FirewallConstants.NET_FW_IP_PROTOCOL_UDP: 577 }
278 break;
279 578
280 default: 579 if (port != null)
281 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "Port", "Protocol", protocol.Value.ToString())); 580 {
282 break; 581 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "Port", "EdgeTraversal", "DeferToUser"));
582 }
583
584 if (remotePort != null)
585 {
586 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "RemotePort", "EdgeTraversal", "DeferToUser"));
587 }
588
589 if (localScope != null)
590 {
591 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "LocalScope", "EdgeTraversal", "DeferToUser"));
592 }
593
594 if (scope != null)
595 {
596 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "Scope", "EdgeTraversal", "DeferToUser"));
597 }
598
599 if (profile != null)
600 {
601 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "Profile", "EdgeTraversal", "DeferToUser"));
602 }
603
604 if (service != null)
605 {
606 if (serviceName != null)
607 {
608 this.Messaging.Write(ErrorMessages.IllegalAttributeValueWhenNested(sourceLineNumbers, element.Name.LocalName, "EdgeTraversal", "DeferToUser", parentElement.Name.LocalName));
609 }
610 else
611 {
612 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "Service", "EdgeTraversal", "DeferToUser"));
613 }
283 } 614 }
284 } 615 }
285 616
286 if (!this.Messaging.EncounteredError) 617 if (!this.Messaging.EncounteredError)
287 { 618 {
288 // at this point, File attribute and File parent element are treated the same 619 // at this point, File attribute and File parent element are treated the same
289 if (null != file) 620 if (file != null)
290 { 621 {
291 fileId = file; 622 fileId = file;
292 } 623 }
@@ -295,28 +626,38 @@ namespace WixToolset.Firewall
295 { 626 {
296 Name = name, 627 Name = name,
297 RemoteAddresses = remoteAddresses, 628 RemoteAddresses = remoteAddresses,
298 Profile = profile ?? FirewallConstants.NET_FW_PROFILE2_ALL,
299 ComponentRef = componentId, 629 ComponentRef = componentId,
300 Description = description, 630 Description = description,
301 Direction = direction ?? FirewallConstants.NET_FW_RULE_DIR_IN, 631 Direction = direction ?? FirewallConstants.NET_FW_RULE_DIR_IN,
632 Action = action ?? FirewallConstants.IntegerNotSetString,
633 EdgeTraversal = edgeTraversal ?? FirewallConstants.IntegerNotSetString,
634 Enabled = enabled ?? FirewallConstants.IntegerNotSetString,
635 Grouping = grouping,
636 IcmpTypesAndCodes = icmpTypesAndCodes,
637 Interfaces = interfaces,
638 InterfaceTypes = interfaceTypes,
639 LocalAddresses = localAddresses,
640 Port = port,
641 Profile = profile ?? FirewallConstants.IntegerNotSetString,
642 Protocol = protocol ?? FirewallConstants.IntegerNotSetString,
643 RemotePort = remotePort,
644 ServiceName = service,
645 LocalAppPackageId = localAppPackageId,
646 LocalUserAuthorizedList = localUserAuthorizedList,
647 LocalUserOwner = localUserOwner,
648 RemoteMachineAuthorizedList = remoteMachineAuthorizedList,
649 RemoteUserAuthorizedList = remoteUserAuthorizedList,
650 SecureFlags = secureFlags ?? FirewallConstants.IntegerNotSetString,
302 }); 651 });
303 652
304 if (!String.IsNullOrEmpty(port)) 653 if (String.IsNullOrEmpty(protocol))
305 { 654 {
306 symbol.Port = port; 655 if (!String.IsNullOrEmpty(port) || !String.IsNullOrEmpty(remotePort))
307
308 if (!protocol.HasValue)
309 { 656 {
310 // default protocol is "TCP" 657 symbol.Protocol = FirewallConstants.NET_FW_IP_PROTOCOL_TCP.ToString();
311 protocol = FirewallConstants.NET_FW_IP_PROTOCOL_TCP;
312 } 658 }
313 } 659 }
314 660
315 if (protocol.HasValue)
316 {
317 symbol.Protocol = protocol.Value;
318 }
319
320 if (!String.IsNullOrEmpty(fileId)) 661 if (!String.IsNullOrEmpty(fileId))
321 { 662 {
322 symbol.Program = $"[#{fileId}]"; 663 symbol.Program = $"[#{fileId}]";
@@ -327,7 +668,7 @@ namespace WixToolset.Firewall
327 symbol.Program = program; 668 symbol.Program = program;
328 } 669 }
329 670
330 if (CompilerConstants.IntegerNotSet != attributes) 671 if (attributes != CompilerConstants.IntegerNotSet)
331 { 672 {
332 symbol.Attributes = attributes; 673 symbol.Attributes = attributes;
333 } 674 }
@@ -382,5 +723,167 @@ namespace WixToolset.Firewall
382 } 723 }
383 } 724 }
384 } 725 }
726
727 /// <summary>
728 /// Parses an Interface element
729 /// </summary>
730 /// <param name="element">The element to parse.</param>
731 private void ParseInterfaceElement(Intermediate intermediate, IntermediateSection section, XElement element, ref string interfaces)
732 {
733 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
734 string name = null;
735
736 // no attributes
737 foreach (var attrib in element.Attributes())
738 {
739 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
740 {
741 switch (attrib.Name.LocalName)
742 {
743 case "Name":
744 name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
745 break;
746 }
747 }
748 else
749 {
750 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
751 }
752 }
753
754 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
755
756 if (String.IsNullOrEmpty(name))
757 {
758 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
759 }
760 else
761 {
762 if (String.IsNullOrEmpty(interfaces))
763 {
764 interfaces = name;
765 }
766 else
767 {
768 interfaces = String.Concat(interfaces, FirewallConstants.FORBIDDEN_FIREWALL_CHAR, name);
769 }
770 }
771 }
772
773 /// <summary>
774 /// Parses an InterfaceType element
775 /// </summary>
776 /// <param name="element">The element to parse.</param>
777 private void ParseInterfaceTypeElement(Intermediate intermediate, IntermediateSection section, XElement element, ref string interfaceTypes)
778 {
779 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
780 string value = null;
781
782 // no attributes
783 foreach (var attrib in element.Attributes())
784 {
785 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
786 {
787 switch (attrib.Name.LocalName)
788 {
789 case "Value":
790 value = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
791 break;
792 }
793 }
794 else
795 {
796 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
797 }
798 }
799
800 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
801
802 if (String.IsNullOrEmpty(value))
803 {
804 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Value"));
805 }
806 else
807 {
808 switch (value)
809 {
810 case "RemoteAccess":
811 case "Wireless":
812 case "Lan":
813 case "All":
814 break;
815
816 default:
817 if (!this.ParseHelper.ContainsProperty(value))
818 {
819 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Value", value, "RemoteAccess", "Wireless", "Lan", "All"));
820 value = null;
821 }
822 break;
823 }
824
825 if (String.IsNullOrEmpty(interfaceTypes))
826 {
827 interfaceTypes = value;
828 }
829 else if (interfaceTypes.Contains("All"))
830 {
831 if (value != "All")
832 {
833 this.Messaging.Write(FirewallErrors.IllegalInterfaceTypeWithInterfaceTypeAll(sourceLineNumbers));
834 }
835 }
836 else if(!String.IsNullOrEmpty(value))
837 {
838 interfaceTypes = String.Concat(interfaceTypes, ",", value);
839 }
840 }
841 }
842
843 /// <summary>
844 /// Parses a RemoteAddress element
845 /// </summary>
846 /// <param name="element">The element to parse.</param>
847 private void ParseLocalAddressElement(Intermediate intermediate, IntermediateSection section, XElement element, ref string localAddresses)
848 {
849 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
850 string address = null;
851
852 // no attributes
853 foreach (var attrib in element.Attributes())
854 {
855 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
856 {
857 switch (attrib.Name.LocalName)
858 {
859 case "Value":
860 address = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
861 break;
862 }
863 }
864 else
865 {
866 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
867 }
868 }
869
870 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
871
872 if (String.IsNullOrEmpty(address))
873 {
874 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Value"));
875 }
876 else
877 {
878 if (String.IsNullOrEmpty(localAddresses))
879 {
880 localAddresses = address;
881 }
882 else
883 {
884 localAddresses = String.Concat(localAddresses, ",", address);
885 }
886 }
887 }
385 } 888 }
386} 889}
diff --git a/src/ext/Firewall/wixext/FirewallConstants.cs b/src/ext/Firewall/wixext/FirewallConstants.cs
index 5ecfe032..b7ed8728 100644
--- a/src/ext/Firewall/wixext/FirewallConstants.cs
+++ b/src/ext/Firewall/wixext/FirewallConstants.cs
@@ -9,6 +9,11 @@ namespace WixToolset.Firewall
9 internal static readonly XNamespace Namespace = "http://wixtoolset.org/schemas/v4/wxs/firewall"; 9 internal static readonly XNamespace Namespace = "http://wixtoolset.org/schemas/v4/wxs/firewall";
10 internal static readonly XName FirewallExceptionName = Namespace + "FirewallException"; 10 internal static readonly XName FirewallExceptionName = Namespace + "FirewallException";
11 internal static readonly XName RemoteAddressName = Namespace + "RemoteAddress"; 11 internal static readonly XName RemoteAddressName = Namespace + "RemoteAddress";
12 internal static readonly XName InterfaceName = Namespace + "Interface";
13 internal static readonly XName InterfaceTypeName = Namespace + "InterfaceType";
14 internal static readonly XName LocalAddressName = Namespace + "LocalAddress";
15
16 internal const string IntegerNotSetString = "-2147483648";
12 17
13 // from icftypes.h 18 // from icftypes.h
14 public const int NET_FW_RULE_DIR_IN = 1; 19 public const int NET_FW_RULE_DIR_IN = 1;
@@ -21,5 +26,17 @@ namespace WixToolset.Firewall
21 public const int NET_FW_PROFILE2_PRIVATE = 0x0002; 26 public const int NET_FW_PROFILE2_PRIVATE = 0x0002;
22 public const int NET_FW_PROFILE2_PUBLIC = 0x0004; 27 public const int NET_FW_PROFILE2_PUBLIC = 0x0004;
23 public const int NET_FW_PROFILE2_ALL = 0x7FFFFFFF; 28 public const int NET_FW_PROFILE2_ALL = 0x7FFFFFFF;
29
30 // from icftypes.h
31 public const int NET_FW_EDGE_TRAVERSAL_TYPE_DENY = 0;
32 public const int NET_FW_EDGE_TRAVERSAL_TYPE_ALLOW = 1;
33 public const int NET_FW_EDGE_TRAVERSAL_TYPE_DEFER_TO_APP = 2;
34 public const int NET_FW_EDGE_TRAVERSAL_TYPE_DEFER_TO_USER = 3;
35
36 /// <summary>
37 /// Firewall rules are stored in the registry.<br/>
38 /// The pipe character is used to split firewall rule attributes, so is not permitted in any of them.
39 /// </summary>
40 public const char FORBIDDEN_FIREWALL_CHAR = '|';
24 } 41 }
25} 42}
diff --git a/src/ext/Firewall/wixext/FirewallDecompiler.cs b/src/ext/Firewall/wixext/FirewallDecompiler.cs
index 9ddd8a9a..7fafab17 100644
--- a/src/ext/Firewall/wixext/FirewallDecompiler.cs
+++ b/src/ext/Firewall/wixext/FirewallDecompiler.cs
@@ -8,6 +8,8 @@ namespace WixToolset.Firewall
8 using WixToolset.Data; 8 using WixToolset.Data;
9 using WixToolset.Data.WindowsInstaller; 9 using WixToolset.Data.WindowsInstaller;
10 using WixToolset.Extensibility; 10 using WixToolset.Extensibility;
11 using WixToolset.Extensibility.Data;
12 using WixToolset.Extensibility.Services;
11 13
12 /// <summary> 14 /// <summary>
13 /// The decompiler for the WiX Toolset Firewall Extension. 15 /// The decompiler for the WiX Toolset Firewall Extension.
@@ -16,6 +18,14 @@ namespace WixToolset.Firewall
16 { 18 {
17 public override IReadOnlyCollection<TableDefinition> TableDefinitions => FirewallTableDefinitions.All; 19 public override IReadOnlyCollection<TableDefinition> TableDefinitions => FirewallTableDefinitions.All;
18 20
21 private IParseHelper ParseHelper { get; set; }
22
23 public override void PreDecompile(IWindowsInstallerDecompileContext context, IWindowsInstallerDecompilerHelper helper)
24 {
25 base.PreDecompile(context, helper);
26 this.ParseHelper = context.ServiceProvider.GetService<IParseHelper>();
27 }
28
19 /// <summary> 29 /// <summary>
20 /// Called at the beginning of the decompilation of a database. 30 /// Called at the beginning of the decompilation of a database.
21 /// </summary> 31 /// </summary>
@@ -32,6 +42,8 @@ namespace WixToolset.Firewall
32 { 42 {
33 switch (table.Name) 43 switch (table.Name)
34 { 44 {
45 case "WixFirewallException":
46 case "Wix4FirewallException":
35 case "Wix5FirewallException": 47 case "Wix5FirewallException":
36 this.DecompileWixFirewallExceptionTable(table); 48 this.DecompileWixFirewallExceptionTable(table);
37 break; 49 break;
@@ -57,7 +69,7 @@ namespace WixToolset.Firewall
57 /// <param name="table">The table to decompile.</param> 69 /// <param name="table">The table to decompile.</param>
58 private void DecompileWixFirewallExceptionTable(Table table) 70 private void DecompileWixFirewallExceptionTable(Table table)
59 { 71 {
60 foreach (Row row in table.Rows) 72 foreach (var row in table.Rows)
61 { 73 {
62 var firewallException = new XElement(FirewallConstants.FirewallExceptionName, 74 var firewallException = new XElement(FirewallConstants.FirewallExceptionName,
63 new XAttribute("Id", row.FieldAsString(0)), 75 new XAttribute("Id", row.FieldAsString(0)),
@@ -90,13 +102,20 @@ namespace WixToolset.Firewall
90 firewallException.Add(new XAttribute("Scope", "defaultGateway")); 102 firewallException.Add(new XAttribute("Scope", "defaultGateway"));
91 break; 103 break;
92 default: 104 default:
93 FirewallDecompiler.AddRemoteAddress(firewallException, addresses[0]); 105 if (this.ParseHelper.ContainsProperty(addresses[0]))
106 {
107 firewallException.Add(new XAttribute("Scope", addresses[0]));
108 }
109 else
110 {
111 FirewallDecompiler.AddRemoteAddress(firewallException, addresses[0]);
112 }
94 break; 113 break;
95 } 114 }
96 } 115 }
97 else 116 else
98 { 117 {
99 foreach (string address in addresses) 118 foreach (var address in addresses)
100 { 119 {
101 FirewallDecompiler.AddRemoteAddress(firewallException, address); 120 FirewallDecompiler.AddRemoteAddress(firewallException, address);
102 } 121 }
@@ -110,16 +129,19 @@ namespace WixToolset.Firewall
110 129
111 if (!row.IsColumnEmpty(4)) 130 if (!row.IsColumnEmpty(4))
112 { 131 {
113 switch (Convert.ToInt32(row[4])) 132 switch (row.FieldAsString(4))
114 { 133 {
115 case FirewallConstants.NET_FW_IP_PROTOCOL_TCP: 134 case FirewallConstants.IntegerNotSetString:
135 break;
136 case "6":
116 firewallException.Add(new XAttribute("Protocol", "tcp")); 137 firewallException.Add(new XAttribute("Protocol", "tcp"));
117 break; 138 break;
118 case FirewallConstants.NET_FW_IP_PROTOCOL_UDP: 139 case "17":
119 firewallException.Add(new XAttribute("Protocol", "udp")); 140 firewallException.Add(new XAttribute("Protocol", "udp"));
120 break; 141 break;
142
121 default: 143 default:
122 firewallException.Add(new XAttribute("Protocol", row[4])); 144 firewallException.Add(new XAttribute("Protocol", row.FieldAsString(4)));
123 break; 145 break;
124 } 146 }
125 } 147 }
@@ -131,26 +153,44 @@ namespace WixToolset.Firewall
131 153
132 if (!row.IsColumnEmpty(6)) 154 if (!row.IsColumnEmpty(6))
133 { 155 {
134 var attr = Convert.ToInt32(row[6]); 156 var attr = row.FieldAsInteger(6);
135 AttributeIfNotNull("IgnoreFailure", (attr & 0x1) == 0x1); 157 if ((attr & 0x1) == 0x1)
158 {
159 AttributeIfNotNull("IgnoreFailure", true);
160 }
161
162 if ((attr & 0x2) == 0x2)
163 {
164 firewallException.Add(new XAttribute("OnUpdate", "DoNothing"));
165 }
166 else if ((attr & 0x4) == 0x4)
167 {
168 firewallException.Add(new XAttribute("OnUpdate", "EnableOnly"));
169 }
136 } 170 }
137 171
138 if (!row.IsColumnEmpty(7)) 172 if (!row.IsColumnEmpty(7))
139 { 173 {
140 switch (Convert.ToInt32(row[7])) 174 switch (row.FieldAsString(7))
141 { 175 {
142 case FirewallConstants.NET_FW_PROFILE2_DOMAIN: 176 case FirewallConstants.IntegerNotSetString:
177 break;
178 case "1":
143 firewallException.Add(new XAttribute("Profile", "domain")); 179 firewallException.Add(new XAttribute("Profile", "domain"));
144 break; 180 break;
145 case FirewallConstants.NET_FW_PROFILE2_PRIVATE: 181 case "2":
146 firewallException.Add(new XAttribute("Profile", "private")); 182 firewallException.Add(new XAttribute("Profile", "private"));
147 break; 183 break;
148 case FirewallConstants.NET_FW_PROFILE2_PUBLIC: 184 case "4":
149 firewallException.Add(new XAttribute("Profile", "public")); 185 firewallException.Add(new XAttribute("Profile", "public"));
150 break; 186 break;
151 case FirewallConstants.NET_FW_PROFILE2_ALL: 187 case "2147483647":
152 firewallException.Add(new XAttribute("Profile", "all")); 188 firewallException.Add(new XAttribute("Profile", "all"));
153 break; 189 break;
190
191 default:
192 firewallException.Add(new XAttribute("Profile", row.FieldAsString(7)));
193 break;
154 } 194 }
155 } 195 }
156 196
@@ -164,8 +204,6 @@ namespace WixToolset.Firewall
164 switch (Convert.ToInt32(row[10])) 204 switch (Convert.ToInt32(row[10]))
165 { 205 {
166 case FirewallConstants.NET_FW_RULE_DIR_IN: 206 case FirewallConstants.NET_FW_RULE_DIR_IN:
167
168 firewallException.Add(AttributeIfNotNull("Outbound", false));
169 break; 207 break;
170 case FirewallConstants.NET_FW_RULE_DIR_OUT: 208 case FirewallConstants.NET_FW_RULE_DIR_OUT:
171 firewallException.Add(AttributeIfNotNull("Outbound", true)); 209 firewallException.Add(AttributeIfNotNull("Outbound", true));
@@ -173,6 +211,224 @@ namespace WixToolset.Firewall
173 } 211 }
174 } 212 }
175 213
214 // Introduced in 5.0.0
215 if (row.Fields.Length > 11)
216 {
217 if (!row.IsColumnEmpty(11))
218 {
219 var action = row.FieldAsString(11);
220 switch (action)
221 {
222 case FirewallConstants.IntegerNotSetString:
223 break;
224 case "1":
225 firewallException.Add(new XAttribute("Action", "Allow"));
226 break;
227 case "0":
228 firewallException.Add(new XAttribute("Action", "Block"));
229 break;
230 default:
231 firewallException.Add(new XAttribute("Action", action));
232 break;
233 }
234 }
235
236 if (!row.IsColumnEmpty(12))
237 {
238 var edgeTraversal = row.FieldAsString(12);
239 switch (edgeTraversal)
240 {
241 case FirewallConstants.IntegerNotSetString:
242 break;
243 case "0":
244 firewallException.Add(new XAttribute("EdgeTraversal", "Deny"));
245 break;
246 case "1":
247 firewallException.Add(new XAttribute("EdgeTraversal", "Allow"));
248 break;
249 case "2":
250 firewallException.Add(new XAttribute("EdgeTraversal", "DeferToApp"));
251 break;
252 case "3":
253 firewallException.Add(new XAttribute("EdgeTraversal", "DeferToUser"));
254 break;
255 default:
256 firewallException.Add(new XAttribute("EdgeTraversal", edgeTraversal));
257 break;
258 }
259 }
260
261 if (!row.IsColumnEmpty(13))
262 {
263 var enabled = row.FieldAsString(13);
264 switch (enabled)
265 {
266 case FirewallConstants.IntegerNotSetString:
267 break;
268 case "1":
269 firewallException.Add(new XAttribute("Enabled", "yes"));
270 break;
271 case "0":
272 firewallException.Add(new XAttribute("Enabled", "no"));
273 break;
274 default:
275 firewallException.Add(new XAttribute("Enabled", enabled));
276 break;
277 }
278 }
279
280 if (!row.IsColumnEmpty(14))
281 {
282 firewallException.Add(new XAttribute("Grouping", row.FieldAsString(14)));
283 }
284
285 if (!row.IsColumnEmpty(15))
286 {
287 firewallException.Add(new XAttribute("IcmpTypesAndCodes", row.FieldAsString(15)));
288 }
289
290 if (!row.IsColumnEmpty(16))
291 {
292 string[] interfaces = row.FieldAsString(16).Split(new[] { FirewallConstants.FORBIDDEN_FIREWALL_CHAR }, StringSplitOptions.RemoveEmptyEntries);
293 if (interfaces.Length == 1)
294 {
295 firewallException.Add(new XAttribute("Interface", interfaces[0]));
296 }
297 else
298 {
299 foreach (var interfaceItem in interfaces)
300 {
301 FirewallDecompiler.AddInterface(firewallException, interfaceItem);
302 }
303 }
304 }
305
306 if (!row.IsColumnEmpty(17))
307 {
308 string[] interfaceTypes = row.FieldAsString(17).Split(',');
309 if (interfaceTypes.Length == 1)
310 {
311 firewallException.Add(new XAttribute("InterfaceType", interfaceTypes[0]));
312 }
313 else
314 {
315 foreach (var interfaceType in interfaceTypes)
316 {
317 FirewallDecompiler.AddInterfaceType(firewallException, interfaceType);
318 }
319 }
320 }
321
322 if (!row.IsColumnEmpty(18))
323 {
324 string[] addresses = row.FieldAsString(18).Split(',');
325 if (addresses.Length == 1)
326 {
327 switch (addresses[0])
328 {
329 case "*":
330 firewallException.Add(new XAttribute("LocalScope", "any"));
331 break;
332 case "LocalSubnet":
333 firewallException.Add(new XAttribute("LocalScope", "localSubnet"));
334 break;
335 case "dns":
336 firewallException.Add(new XAttribute("LocalScope", "DNS"));
337 break;
338 case "dhcp":
339 firewallException.Add(new XAttribute("LocalScope", "DHCP"));
340 break;
341 case "wins":
342 firewallException.Add(new XAttribute("LocalScope", "WINS"));
343 break;
344 case "DefaultGateway":
345 firewallException.Add(new XAttribute("LocalScope", "defaultGateway"));
346 break;
347 default:
348 if (this.ParseHelper.ContainsProperty(addresses[0]))
349 {
350 firewallException.Add(new XAttribute("LocalScope", addresses[0]));
351 }
352 else
353 {
354 FirewallDecompiler.AddLocalAddress(firewallException, addresses[0]);
355 }
356 break;
357 }
358 }
359 else
360 {
361 foreach (var address in addresses)
362 {
363 FirewallDecompiler.AddLocalAddress(firewallException, address);
364 }
365 }
366 }
367
368 if (!row.IsColumnEmpty(19))
369 {
370 firewallException.Add(new XAttribute("RemotePort", row.FieldAsString(19)));
371 }
372
373 if (!row.IsColumnEmpty(20))
374 {
375 firewallException.Add(new XAttribute("Service", row.FieldAsString(20)));
376 }
377
378 if (!row.IsColumnEmpty(21))
379 {
380 firewallException.Add(new XAttribute("LocalAppPackageId", row.FieldAsString(21)));
381 }
382
383 if (!row.IsColumnEmpty(22))
384 {
385 firewallException.Add(new XAttribute("LocalUserAuthorizedList", row.FieldAsString(22)));
386 }
387
388 if (!row.IsColumnEmpty(23))
389 {
390 firewallException.Add(new XAttribute("LocalUserOwner", row.FieldAsString(23)));
391 }
392
393 if (!row.IsColumnEmpty(24))
394 {
395 firewallException.Add(new XAttribute("RemoteMachineAuthorizedList", row.FieldAsString(24)));
396 }
397
398 if (!row.IsColumnEmpty(25))
399 {
400 firewallException.Add(new XAttribute("RemoteUserAuthorizedList", row.FieldAsString(25)));
401 }
402
403 if (!row.IsColumnEmpty(26))
404 {
405 var secureFlags = row.FieldAsString(26);
406 switch (secureFlags)
407 {
408 case FirewallConstants.IntegerNotSetString:
409 break;
410 case "0":
411 firewallException.Add(new XAttribute("IPSecSecureFlags", "None"));
412 break;
413 case "1":
414 firewallException.Add(new XAttribute("IPSecSecureFlags", "NoEncapsulation"));
415 break;
416 case "2":
417 firewallException.Add(new XAttribute("IPSecSecureFlags", "WithIntegrity"));
418 break;
419 case "3":
420 firewallException.Add(new XAttribute("IPSecSecureFlags", "NegotiateEncryption"));
421 break;
422 case "4":
423 firewallException.Add(new XAttribute("IPSecSecureFlags", "Encrypt"));
424 break;
425 default:
426 firewallException.Add(new XAttribute("IPSecSecureFlags", secureFlags));
427 break;
428 }
429 }
430 }
431
176 this.DecompilerHelper.IndexElement(row, firewallException); 432 this.DecompilerHelper.IndexElement(row, firewallException);
177 } 433 }
178 } 434 }
@@ -183,7 +439,34 @@ namespace WixToolset.Firewall
183 new XAttribute("Value", address) 439 new XAttribute("Value", address)
184 ); 440 );
185 441
186 firewallException.AddAfterSelf(remoteAddress); 442 firewallException.Add(remoteAddress);
443 }
444
445 private static void AddInterfaceType(XElement firewallException, string type)
446 {
447 var interfaceType = new XElement(FirewallConstants.InterfaceTypeName,
448 new XAttribute("Value", type)
449 );
450
451 firewallException.Add(interfaceType);
452 }
453
454 private static void AddLocalAddress(XElement firewallException, string address)
455 {
456 var localAddress = new XElement(FirewallConstants.LocalAddressName,
457 new XAttribute("Value", address)
458 );
459
460 firewallException.Add(localAddress);
461 }
462
463 private static void AddInterface(XElement firewallException, string value)
464 {
465 var interfaceName = new XElement(FirewallConstants.InterfaceName,
466 new XAttribute("Name", value)
467 );
468
469 firewallException.Add(interfaceName);
187 } 470 }
188 471
189 private static XAttribute AttributeIfNotNull(string name, bool value) 472 private static XAttribute AttributeIfNotNull(string name, bool value)
diff --git a/src/ext/Firewall/wixext/FirewallErrors.cs b/src/ext/Firewall/wixext/FirewallErrors.cs
index b2dac782..523398e5 100644
--- a/src/ext/Firewall/wixext/FirewallErrors.cs
+++ b/src/ext/Firewall/wixext/FirewallErrors.cs
@@ -12,11 +12,6 @@ namespace WixToolset.Firewall
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."); 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 } 13 }
14 14
15 public static Message NoExceptionSpecified(SourceLineNumber sourceLineNumbers)
16 {
17 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.");
18 }
19
20 private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args) 15 private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args)
21 { 16 {
22 return new Message(sourceLineNumber, MessageLevel.Error, (int)id, format, args); 17 return new Message(sourceLineNumber, MessageLevel.Error, (int)id, format, args);
@@ -27,10 +22,32 @@ namespace WixToolset.Firewall
27 return new Message(sourceLineNumber, MessageLevel.Error, (int)id, resourceManager, resourceName, args); 22 return new Message(sourceLineNumber, MessageLevel.Error, (int)id, resourceManager, resourceName, args);
28 } 23 }
29 24
25 public static Message IllegalInterfaceWithInterfaceAttribute(SourceLineNumber sourceLineNumbers)
26 {
27 return Message(sourceLineNumbers, Ids.IllegalInterfaceWithInterfaceAttribute, "The Interface element cannot be specified because its parent FirewallException already specified the Interface attribute. To use Interface elements, omit the Interface attribute.");
28 }
29
30 public static Message IllegalInterfaceTypeWithInterfaceTypeAttribute(SourceLineNumber sourceLineNumbers)
31 {
32 return Message(sourceLineNumbers, Ids.IllegalInterfaceTypeWithInterfaceTypeAttribute, "The InterfaceType element cannot be specified because its parent FirewallException already specified the InterfaceType attribute. To use InterfaceType elements, omit the InterfaceType attribute.");
33 }
34
35 public static Message IllegalInterfaceTypeWithInterfaceTypeAll(SourceLineNumber sourceLineNumbers)
36 {
37 return Message(sourceLineNumbers, Ids.IllegalInterfaceTypeWithInterfaceTypeAll, "The InterfaceType element cannot be specified because its parent FirewallException contains another InterfaceType element with value 'All'.");
38 }
39 public static Message IllegalLocalAddressWithLocalScopeAttribute(SourceLineNumber sourceLineNumbers)
40 {
41 return Message(sourceLineNumbers, Ids.IllegalLocalAddressWithLocalScopeAttribute, "The LocalAddress element cannot be specified because its parent FirewallException already specified the LocalScope attribute. To use LocalAddress elements, omit the LocalScope attribute.");
42 }
43
30 public enum Ids 44 public enum Ids
31 { 45 {
32 IllegalRemoteAddressWithScopeAttribute = 6401, 46 IllegalRemoteAddressWithScopeAttribute = 6401,
33 NoExceptionSpecified = 6403, 47 IllegalInterfaceWithInterfaceAttribute = 6402,
48 IllegalInterfaceTypeWithInterfaceTypeAttribute = 6404,
49 IllegalInterfaceTypeWithInterfaceTypeAll = 6405,
50 IllegalLocalAddressWithLocalScopeAttribute = 6406,
34 } 51 }
35 } 52 }
36} 53}
diff --git a/src/ext/Firewall/wixext/FirewallTableDefinitions.cs b/src/ext/Firewall/wixext/FirewallTableDefinitions.cs
index 26dedbf1..7a35bb59 100644
--- a/src/ext/Firewall/wixext/FirewallTableDefinitions.cs
+++ b/src/ext/Firewall/wixext/FirewallTableDefinitions.cs
@@ -13,15 +13,31 @@ namespace WixToolset.Firewall
13 { 13 {
14 new ColumnDefinition("Wix5FirewallException", 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: true, 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, maxValue: 65535, description: "Local Port number.", modularizeType: ColumnModularizeType.Property),
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"), 18 new ColumnDefinition("Protocol", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, minValue: 0, maxValue: 255, description: "Protocol (6=TCP; 17=UDP). https://www.iana.org/assignments/protocol-numbers", 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), 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; IgnoreUpdates=2; EnableOnChange=4; INetFwRule2=8; INetFwRule3=16"),
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.String, 4, primaryKey: false, nullable: true, ColumnCategory.Formatted, minValue: 1, maxValue: 2147483647, description: "Profile (1=domain; 2=private; 4=public; 2147483647=all).", modularizeType: ColumnModularizeType.Property),
22 new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table referencing component that controls the firewall configuration.", modularizeType: ColumnModularizeType.Column), 22 new ColumnDefinition("Component_", ColumnType.String, 72, primaryKey: false, nullable: false, ColumnCategory.Identifier, keyTable: "Component", keyColumn: 1, description: "Foreign key into the Component table referencing component that controls the firewall configuration.", modularizeType: ColumnModularizeType.Column),
23 new ColumnDefinition("Description", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Description displayed in Windows Firewall manager for this firewall rule."), 23 new ColumnDefinition("Description", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Description displayed in Windows Firewall manager for this firewall rule."),
24 new ColumnDefinition("Direction", ColumnType.Number, 1, primaryKey: false, nullable: true, ColumnCategory.Integer, minValue: 1, maxValue: 2, description: "Direction (1=in; 2=out)"), 24 new ColumnDefinition("Direction", ColumnType.Number, 1, primaryKey: false, nullable: false, ColumnCategory.Integer, minValue: 1, maxValue: 2, description: "Direction (1=in; 2=out)"),
25 new ColumnDefinition("Action", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, minValue: 0, maxValue: 1, description: "Action (0=Block; 1=Allow).", modularizeType: ColumnModularizeType.Property),
26 new ColumnDefinition("EdgeTraversal", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, minValue: 0, maxValue: 3, description: "Edge traversal (0=Deny; 1=Allow; 2=DeferToApp; 3=DeferToUser).", modularizeType: ColumnModularizeType.Property),
27 new ColumnDefinition("Enabled", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, minValue: 0, maxValue: 1, description: "Enabled (0=Disabled; 1=Enabled).", modularizeType: ColumnModularizeType.Property),
28 new ColumnDefinition("Grouping", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "The group to which the rule belongs.", modularizeType: ColumnModularizeType.Property),
29 new ColumnDefinition("IcmpTypesAndCodes", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Comma separated list of ICMP types and codes separated by colons.", modularizeType: ColumnModularizeType.Property),
30 new ColumnDefinition("Interfaces", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "A list of network interfaces separated by a pipe character.", modularizeType: ColumnModularizeType.Property),
31 new ColumnDefinition("InterfaceTypes", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Comma separated list of interface types (combination of Wireless,Lan,RemoteAccess or All).", modularizeType: ColumnModularizeType.Property),
32 new ColumnDefinition("LocalAddresses", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Local address to accept incoming connections on.", modularizeType: ColumnModularizeType.Property),
33 new ColumnDefinition("RemotePort", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, minValue: 1, maxValue: 65535, description: "Remote Port number.", modularizeType: ColumnModularizeType.Property),
34 new ColumnDefinition("ServiceName", ColumnType.String, 256, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Windows Service short name.", modularizeType: ColumnModularizeType.Property),
35 new ColumnDefinition("LocalAppPackageId", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Package identifier or the app container identifier of a process.", modularizeType: ColumnModularizeType.Property),
36 new ColumnDefinition("LocalUserAuthorizedList", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "List of authorized local users for an app container.", modularizeType: ColumnModularizeType.Property),
37 new ColumnDefinition("LocalUserOwner", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "SID of the user who is the owner of the rule.", modularizeType: ColumnModularizeType.Property),
38 new ColumnDefinition("RemoteMachineAuthorizedList", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "List of remote computers which are authorized to access an app container.", modularizeType: ColumnModularizeType.Property),
39 new ColumnDefinition("RemoteUserAuthorizedList", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "List of remote users who are authorized to access an app container.", modularizeType: ColumnModularizeType.Property),
40 new ColumnDefinition("SecureFlags", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, minValue: 0, maxValue: 1, description: "NET_FW_AUTHENTICATE_TYPE IPsec verification level.", modularizeType: ColumnModularizeType.Property),
25 }, 41 },
26 symbolIdIsPrimaryKey: true 42 symbolIdIsPrimaryKey: true
27 ); 43 );
diff --git a/src/ext/Firewall/wixext/Symbols/WixFirewallExceptionSymbol.cs b/src/ext/Firewall/wixext/Symbols/WixFirewallExceptionSymbol.cs
index 620de969..d6a54255 100644
--- a/src/ext/Firewall/wixext/Symbols/WixFirewallExceptionSymbol.cs
+++ b/src/ext/Firewall/wixext/Symbols/WixFirewallExceptionSymbol.cs
@@ -14,13 +14,29 @@ namespace WixToolset.Firewall
14 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Name), IntermediateFieldType.String), 14 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Name), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.RemoteAddresses), IntermediateFieldType.String), 15 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.RemoteAddresses), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Port), IntermediateFieldType.String), 16 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Port), IntermediateFieldType.String),
17 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Protocol), IntermediateFieldType.Number), 17 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Protocol), IntermediateFieldType.String),
18 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Program), IntermediateFieldType.String), 18 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Program), IntermediateFieldType.String),
19 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Attributes), IntermediateFieldType.Number), 19 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Attributes), IntermediateFieldType.Number),
20 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Profile), IntermediateFieldType.Number), 20 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Profile), IntermediateFieldType.String),
21 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.ComponentRef), IntermediateFieldType.String), 21 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.ComponentRef), IntermediateFieldType.String),
22 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Description), IntermediateFieldType.String), 22 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Description), IntermediateFieldType.String),
23 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Direction), IntermediateFieldType.Number), 23 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Direction), IntermediateFieldType.Number),
24 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Action), IntermediateFieldType.String),
25 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.EdgeTraversal), IntermediateFieldType.String),
26 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Enabled), IntermediateFieldType.String),
27 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Grouping), IntermediateFieldType.String),
28 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.IcmpTypesAndCodes), IntermediateFieldType.String),
29 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Interfaces), IntermediateFieldType.String),
30 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.InterfaceTypes), IntermediateFieldType.String),
31 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.LocalAddresses), IntermediateFieldType.String),
32 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.RemotePort), IntermediateFieldType.String),
33 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.ServiceName), IntermediateFieldType.String),
34 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.LocalAppPackageId), IntermediateFieldType.String),
35 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.LocalUserAuthorizedList), IntermediateFieldType.String),
36 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.LocalUserOwner), IntermediateFieldType.String),
37 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.RemoteMachineAuthorizedList), IntermediateFieldType.String),
38 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.RemoteUserAuthorizedList), IntermediateFieldType.String),
39 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.SecureFlags), IntermediateFieldType.String),
24 }, 40 },
25 typeof(WixFirewallExceptionSymbol)); 41 typeof(WixFirewallExceptionSymbol));
26 } 42 }
@@ -42,6 +58,22 @@ namespace WixToolset.Firewall.Symbols
42 ComponentRef, 58 ComponentRef,
43 Description, 59 Description,
44 Direction, 60 Direction,
61 Action,
62 EdgeTraversal,
63 Enabled,
64 Grouping,
65 IcmpTypesAndCodes,
66 Interfaces,
67 InterfaceTypes,
68 LocalAddresses,
69 RemotePort,
70 ServiceName,
71 LocalAppPackageId,
72 LocalUserAuthorizedList,
73 LocalUserOwner,
74 RemoteMachineAuthorizedList,
75 RemoteUserAuthorizedList,
76 SecureFlags,
45 } 77 }
46 78
47 public class WixFirewallExceptionSymbol : IntermediateSymbol 79 public class WixFirewallExceptionSymbol : IntermediateSymbol
@@ -74,9 +106,9 @@ namespace WixToolset.Firewall.Symbols
74 set => this.Set((int)WixFirewallExceptionSymbolFields.Port, value); 106 set => this.Set((int)WixFirewallExceptionSymbolFields.Port, value);
75 } 107 }
76 108
77 public int? Protocol 109 public string Protocol
78 { 110 {
79 get => this.Fields[(int)WixFirewallExceptionSymbolFields.Protocol].AsNullableNumber(); 111 get => this.Fields[(int)WixFirewallExceptionSymbolFields.Protocol].AsString();
80 set => this.Set((int)WixFirewallExceptionSymbolFields.Protocol, value); 112 set => this.Set((int)WixFirewallExceptionSymbolFields.Protocol, value);
81 } 113 }
82 114
@@ -92,9 +124,9 @@ namespace WixToolset.Firewall.Symbols
92 set => this.Set((int)WixFirewallExceptionSymbolFields.Attributes, value); 124 set => this.Set((int)WixFirewallExceptionSymbolFields.Attributes, value);
93 } 125 }
94 126
95 public int Profile 127 public string Profile
96 { 128 {
97 get => this.Fields[(int)WixFirewallExceptionSymbolFields.Profile].AsNumber(); 129 get => this.Fields[(int)WixFirewallExceptionSymbolFields.Profile].AsString();
98 set => this.Set((int)WixFirewallExceptionSymbolFields.Profile, value); 130 set => this.Set((int)WixFirewallExceptionSymbolFields.Profile, value);
99 } 131 }
100 132
@@ -115,5 +147,101 @@ namespace WixToolset.Firewall.Symbols
115 get => this.Fields[(int)WixFirewallExceptionSymbolFields.Direction].AsNumber(); 147 get => this.Fields[(int)WixFirewallExceptionSymbolFields.Direction].AsNumber();
116 set => this.Set((int)WixFirewallExceptionSymbolFields.Direction, value); 148 set => this.Set((int)WixFirewallExceptionSymbolFields.Direction, value);
117 } 149 }
150
151 public string Action
152 {
153 get => this.Fields[(int)WixFirewallExceptionSymbolFields.Action].AsString();
154 set => this.Set((int)WixFirewallExceptionSymbolFields.Action, value);
155 }
156
157 public string EdgeTraversal
158 {
159 get => this.Fields[(int)WixFirewallExceptionSymbolFields.EdgeTraversal].AsString();
160 set => this.Set((int)WixFirewallExceptionSymbolFields.EdgeTraversal, value);
161 }
162
163 public string Enabled
164 {
165 get => this.Fields[(int)WixFirewallExceptionSymbolFields.Enabled].AsString();
166 set => this.Set((int)WixFirewallExceptionSymbolFields.Enabled, value);
167 }
168
169 public string Grouping
170 {
171 get => this.Fields[(int)WixFirewallExceptionSymbolFields.Grouping].AsString();
172 set => this.Set((int)WixFirewallExceptionSymbolFields.Grouping, value);
173 }
174
175 public string IcmpTypesAndCodes
176 {
177 get => this.Fields[(int)WixFirewallExceptionSymbolFields.IcmpTypesAndCodes].AsString();
178 set => this.Set((int)WixFirewallExceptionSymbolFields.IcmpTypesAndCodes, value);
179 }
180
181 public string Interfaces
182 {
183 get => this.Fields[(int)WixFirewallExceptionSymbolFields.Interfaces].AsString();
184 set => this.Set((int)WixFirewallExceptionSymbolFields.Interfaces, value);
185 }
186
187 public string InterfaceTypes
188 {
189 get => this.Fields[(int)WixFirewallExceptionSymbolFields.InterfaceTypes].AsString();
190 set => this.Set((int)WixFirewallExceptionSymbolFields.InterfaceTypes, value);
191 }
192
193 public string LocalAddresses
194 {
195 get => this.Fields[(int)WixFirewallExceptionSymbolFields.LocalAddresses].AsString();
196 set => this.Set((int)WixFirewallExceptionSymbolFields.LocalAddresses, value);
197 }
198
199 public string RemotePort
200 {
201 get => this.Fields[(int)WixFirewallExceptionSymbolFields.RemotePort].AsString();
202 set => this.Set((int)WixFirewallExceptionSymbolFields.RemotePort, value);
203 }
204
205 public string ServiceName
206 {
207 get => this.Fields[(int)WixFirewallExceptionSymbolFields.ServiceName].AsString();
208 set => this.Set((int)WixFirewallExceptionSymbolFields.ServiceName, value);
209 }
210
211 public string LocalAppPackageId
212 {
213 get => this.Fields[(int)WixFirewallExceptionSymbolFields.LocalAppPackageId].AsString();
214 set => this.Set((int)WixFirewallExceptionSymbolFields.LocalAppPackageId, value);
215 }
216
217 public string LocalUserAuthorizedList
218 {
219 get => this.Fields[(int)WixFirewallExceptionSymbolFields.LocalUserAuthorizedList].AsString();
220 set => this.Set((int)WixFirewallExceptionSymbolFields.LocalUserAuthorizedList, value);
221 }
222
223 public string LocalUserOwner
224 {
225 get => this.Fields[(int)WixFirewallExceptionSymbolFields.LocalUserOwner].AsString();
226 set => this.Set((int)WixFirewallExceptionSymbolFields.LocalUserOwner, value);
227 }
228
229 public string RemoteMachineAuthorizedList
230 {
231 get => this.Fields[(int)WixFirewallExceptionSymbolFields.RemoteMachineAuthorizedList].AsString();
232 set => this.Set((int)WixFirewallExceptionSymbolFields.RemoteMachineAuthorizedList, value);
233 }
234
235 public string RemoteUserAuthorizedList
236 {
237 get => this.Fields[(int)WixFirewallExceptionSymbolFields.RemoteUserAuthorizedList].AsString();
238 set => this.Set((int)WixFirewallExceptionSymbolFields.RemoteUserAuthorizedList, value);
239 }
240
241 public string SecureFlags
242 {
243 get => this.Fields[(int)WixFirewallExceptionSymbolFields.SecureFlags].AsString();
244 set => this.Set((int)WixFirewallExceptionSymbolFields.SecureFlags, value);
245 }
118 } 246 }
119} \ No newline at end of file 247}
diff --git a/src/ext/Firewall/wixext/WixToolset.Firewall.wixext.csproj b/src/ext/Firewall/wixext/WixToolset.Firewall.wixext.csproj
index 8d1dc77e..098b121c 100644
--- a/src/ext/Firewall/wixext/WixToolset.Firewall.wixext.csproj
+++ b/src/ext/Firewall/wixext/WixToolset.Firewall.wixext.csproj
@@ -5,9 +5,11 @@
5 <PropertyGroup> 5 <PropertyGroup>
6 <TargetFramework>netstandard2.0</TargetFramework> 6 <TargetFramework>netstandard2.0</TargetFramework>
7 <RootNamespace>WixToolset.Firewall</RootNamespace> 7 <RootNamespace>WixToolset.Firewall</RootNamespace>
8 <Description>WiX Toolset Firewallity Extension</Description> 8 <Description>WiX Toolset Firewall Extension</Description>
9 <Title>WiX Toolset Firewall Extension</Title> 9 <Title>WiX Toolset Firewall Extension</Title>
10 <DebugType>embedded</DebugType> 10 <DebugType>embedded</DebugType>
11 <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
12 <GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
11 </PropertyGroup> 13 </PropertyGroup>
12 14
13 <Import Project="..\..\WixExt.props" /> 15 <Import Project="..\..\WixExt.props" />
diff --git a/src/ext/Util/wixext/UtilCompiler.cs b/src/ext/Util/wixext/UtilCompiler.cs
index 5fefed91..f7bb0614 100644
--- a/src/ext/Util/wixext/UtilCompiler.cs
+++ b/src/ext/Util/wixext/UtilCompiler.cs
@@ -3123,8 +3123,14 @@ namespace WixToolset.Util
3123 // if this element is a child of ServiceInstall then ignore the service name provided. 3123 // if this element is a child of ServiceInstall then ignore the service name provided.
3124 if ("ServiceInstall" == parentTableName) 3124 if ("ServiceInstall" == parentTableName)
3125 { 3125 {
3126 // TODO: the ServiceName attribute should not be allowed in this case (the overwriting behavior may confuse users) 3126 if (null == serviceName || parentTableServiceName == serviceName)
3127 serviceName = parentTableServiceName; 3127 {
3128 serviceName = parentTableServiceName;
3129 }
3130 else
3131 {
3132 this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, "ServiceName", parentTableName));
3133 }
3128 newService = true; 3134 newService = true;
3129 } 3135 }
3130 else 3136 else
@@ -3136,7 +3142,8 @@ namespace WixToolset.Util
3136 } 3142 }
3137 } 3143 }
3138 3144
3139 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); 3145 var context = new Dictionary<string, string>() { { "ServiceConfigComponentId", componentId }, { "ServiceConfigServiceName", serviceName } };
3146 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element, context);
3140 3147
3141 if (!this.Messaging.EncounteredError) 3148 if (!this.Messaging.EncounteredError)
3142 { 3149 {
diff --git a/src/internal/SetBuildNumber/Directory.Packages.props.pp b/src/internal/SetBuildNumber/Directory.Packages.props.pp
index b39eeb78..ead26299 100644
--- a/src/internal/SetBuildNumber/Directory.Packages.props.pp
+++ b/src/internal/SetBuildNumber/Directory.Packages.props.pp
@@ -47,6 +47,7 @@
47 <PackageVersion Include="System.DirectoryServices.AccountManagement" Version="4.7.0" /> 47 <PackageVersion Include="System.DirectoryServices.AccountManagement" Version="4.7.0" />
48 <PackageVersion Include="System.IO.Compression" Version="4.3.0" /> 48 <PackageVersion Include="System.IO.Compression" Version="4.3.0" />
49 <PackageVersion Include="System.IO.FileSystem.AccessControl" Version="4.7.0" /> 49 <PackageVersion Include="System.IO.FileSystem.AccessControl" Version="4.7.0" />
50 <PackageVersion Include="System.Net.NetworkInformation" Version="4.3.0" />
50 <PackageVersion Include="System.Reflection.Metadata" Version="1.6.0" /> 51 <PackageVersion Include="System.Reflection.Metadata" Version="1.6.0" />
51 <PackageVersion Include="System.Security.Principal.Windows" Version="4.7.0" /> 52 <PackageVersion Include="System.Security.Principal.Windows" Version="4.7.0" />
52 <PackageVersion Include="System.Text.Encoding.CodePages" Version="4.7.0" /> 53 <PackageVersion Include="System.Text.Encoding.CodePages" Version="4.7.0" />
diff --git a/src/test/burn/WixTestTools/Firewall/RuleDetails.cs b/src/test/burn/WixTestTools/Firewall/RuleDetails.cs
index d1e53de4..8c8cdda3 100644
--- a/src/test/burn/WixTestTools/Firewall/RuleDetails.cs
+++ b/src/test/burn/WixTestTools/Firewall/RuleDetails.cs
@@ -146,7 +146,9 @@ namespace WixTestTools.Firewall
146 /// This parameter allows the specification of an array of interface LUIDs (locally unique identifiers) supplied as strings.<br/> 146 /// This parameter allows the specification of an array of interface LUIDs (locally unique identifiers) supplied as strings.<br/>
147 /// This is commonly used by USB RNDIS (Remote Network Driver Interface Specification) devices to restrict traffic to a specific non-routable interface.<br/> 147 /// This is commonly used by USB RNDIS (Remote Network Driver Interface Specification) devices to restrict traffic to a specific non-routable interface.<br/>
148 /// Use <b>netsh trace show interfaces</b> to show a list of local interfaces and their LUIDs.<br/> 148 /// Use <b>netsh trace show interfaces</b> to show a list of local interfaces and their LUIDs.<br/>
149 /// Example: new object[] { "Wi-Fi", "Local Area Connection* 14" } 149 /// The interfaces are stored in the registry as GUIDs, but need to be passed to the API as text. eg from the registry<br/>
150 /// v2.30|Action=Allow|Active=TRUE|Dir=In|Protocol=6|LPort=23456|IF={423411CD-E627-4A1A-9E1F-C5BE6CD2CC99}|IF={49A98AD0-8379-4079-A445-77066C52E338}|Name=WiXToolset401 Test - 0002|Desc=WiX Toolset firewall exception rule integration test - minimal port properties|<br/>
151 /// Example API value: new object[] { "Wi-Fi", "Local Area Connection* 14" }
150 /// </summary> 152 /// </summary>
151 public object[] Interfaces { get; set; } 153 public object[] Interfaces { get; set; }
152 154
@@ -227,13 +229,13 @@ namespace WixTestTools.Firewall
227 public string LocalUserOwner { get; set; } 229 public string LocalUserOwner { get; set; }
228 230
229 /// <summary> 231 /// <summary>
230 /// This property is optional. It specifies a list of authorized local users for an app container.<br/> 232 /// This property is optional. It specifies a list of authorized local users for an app container (using SDDL).<br/>
231 /// Example: "O:LSD:(A;;CC;;;S-1-5-84-0-0-0-0-0)" 233 /// Example: "O:LSD:(A;;CC;;;S-1-5-84-0-0-0-0-0)"
232 /// </summary> 234 /// </summary>
233 public string LocalUserAuthorizedList { get; set; } 235 public string LocalUserAuthorizedList { get; set; }
234 236
235 /// <summary> 237 /// <summary>
236 /// This property is optional. It specifies a list of remote users who are authorized to access an app container.<br/> 238 /// This property is optional. It specifies a list of remote users who are authorized to access an app container (using SDDL).<br/>
237 /// </summary> 239 /// </summary>
238 public string RemoteUserAuthorizedList { get; set; } 240 public string RemoteUserAuthorizedList { get; set; }
239 241
diff --git a/src/test/msi/TestData/FirewallExtensionTests/CrossVersionMerge/CrossVersionMerge.wixproj b/src/test/msi/TestData/FirewallExtensionTests/CrossVersionMerge/CrossVersionMerge.wixproj
new file mode 100644
index 00000000..f1c71d3d
--- /dev/null
+++ b/src/test/msi/TestData/FirewallExtensionTests/CrossVersionMerge/CrossVersionMerge.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 <SuppressSpecificWarnings>1055;1056</SuppressSpecificWarnings>
5 </PropertyGroup>
6 <ItemGroup>
7 <!-- <ProjectReference Include="..\Module401\Module401.wixproj" /> -->
8 <ProjectReference Include="..\ModuleCurrent\ModuleCurrent.wixproj" />
9 </ItemGroup>
10 <ItemGroup>
11 <PackageReference Include="WixToolset.Firewall.wixext" />
12 </ItemGroup>
13</Project>
diff --git a/src/test/msi/TestData/FirewallExtensionTests/CrossVersionMerge/Module401.msm b/src/test/msi/TestData/FirewallExtensionTests/CrossVersionMerge/Module401.msm
new file mode 100644
index 00000000..4dd5bd09
--- /dev/null
+++ b/src/test/msi/TestData/FirewallExtensionTests/CrossVersionMerge/Module401.msm
Binary files differ
diff --git a/src/test/msi/TestData/FirewallExtensionTests/CrossVersionMerge/package.wxs b/src/test/msi/TestData/FirewallExtensionTests/CrossVersionMerge/package.wxs
new file mode 100644
index 00000000..6d5ea47a
--- /dev/null
+++ b/src/test/msi/TestData/FirewallExtensionTests/CrossVersionMerge/package.wxs
@@ -0,0 +1,35 @@
1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:fw="http://wixtoolset.org/schemas/v4/wxs/firewall">
2 <Package Name="MsiPackage" Language="1033" Version="1.0.0.0" Manufacturer="Example Corporation"
3 UpgradeCode="41B5F815-E7F6-44E0-B92A-AE95DFF683F9" Compressed="yes" Scope="perMachine">
4 <MediaTemplate EmbedCab="yes" />
5
6 <MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
7
8 <Feature Id="ProductFeature" Title="Feature with merged modules">
9 <MergeRef Id="TestMsm1" />
10 <MergeRef Id="TestMsm2" />
11 <ComponentRef Id="FirewallComponent1" />
12 </Feature>
13 </Package>
14
15 <Fragment>
16 <StandardDirectory Id="ProgramFilesFolder">
17 <Directory Id="INSTALLFOLDER" Name="MsiPackage">
18 <Merge Id="TestMsm1" Language="1033" SourceFile="Module401.msm" />
19 <Merge Id="TestMsm2" Language="1033" SourceFile="ModuleCurrent.msm" />
20 </Directory>
21 </StandardDirectory>
22 </Fragment>
23
24 <Fragment>
25 <Property Id="MSIPORT1" Value="20001" />
26 <Property Id="MSIPORT2" Value="20002" />
27
28 <Component Id="FirewallComponent1" Guid="3E9A6190-3E6B-4BC2-8C84-D89D1549FEBD" Directory="INSTALLFOLDER">
29 <File Source="$(sys.SOURCEFILEPATH)">
30 <fw:FirewallException Id="FirewallException1" Description="WiX Toolset firewall exception rule integration test - package app" Name="WiXToolset Test - 0026" Scope="any" Port="[MSIPORT1]" />
31 </File>
32 <fw:FirewallException Id="FirewallException2" Description="WiX Toolset firewall exception rule integration test - package port" Name="WiXToolset Test - 0027" Scope="any" Port="[MSIPORT2]" />
33 </Component>
34 </Fragment>
35</Wix>
diff --git a/src/test/msi/TestData/FirewallExtensionTests/FirewallRulesInterfaces/FirewallRulesInterfaces.wixproj b/src/test/msi/TestData/FirewallExtensionTests/FirewallRulesInterfaces/FirewallRulesInterfaces.wixproj
new file mode 100644
index 00000000..3c6ef5cf
--- /dev/null
+++ b/src/test/msi/TestData/FirewallExtensionTests/FirewallRulesInterfaces/FirewallRulesInterfaces.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>{F153C27F-0236-4A0F-ADB3-50BFC73B4FEA}</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/FirewallRulesInterfaces/product.wxs b/src/test/msi/TestData/FirewallExtensionTests/FirewallRulesInterfaces/product.wxs
new file mode 100644
index 00000000..142c8f68
--- /dev/null
+++ b/src/test/msi/TestData/FirewallExtensionTests/FirewallRulesInterfaces/product.wxs
@@ -0,0 +1,32 @@
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="08044660-CB5D-4891-8BD5-0CB5BB668D78" Directory="INSTALLFOLDER">
13 <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" >
14 <fw:FirewallException Id="FirewallException28"
15 Description="WiX Toolset firewall exception rule integration test - three interfaces"
16 Name="WiXToolset500 Test - 0028" Scope="any" >
17 <fw:Interface Name="[INTERFACE1]" />
18 <fw:Interface Name="[INTERFACE2]" />
19 <fw:Interface Name="[INTERFACE3]" />
20 <fw:InterfaceType Value="RemoteAccess" />
21 <fw:InterfaceType Value="Lan" />
22 <fw:InterfaceType Value="Wireless" />
23 </fw:FirewallException>
24 </File>
25
26 <fw:FirewallException Id="FirewallException29"
27 Description="WiX Toolset firewall exception rule integration test - one interface"
28 Name="WiXToolset500 Test - 0029" Scope="any" Port="29292" Interface="[INTERFACE1]" InterfaceType="[INTERFACETYPE]" >
29 </fw:FirewallException>
30 </Component>
31 </Fragment>
32</Wix>
diff --git a/src/test/msi/TestData/FirewallExtensionTests/FirewallRulesProperties/FirewallRulesProperties.wixproj b/src/test/msi/TestData/FirewallExtensionTests/FirewallRulesProperties/FirewallRulesProperties.wixproj
new file mode 100644
index 00000000..38d94265
--- /dev/null
+++ b/src/test/msi/TestData/FirewallExtensionTests/FirewallRulesProperties/FirewallRulesProperties.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>{DC2C3CDC-112F-40A8-A7B4-2C7B758F4F94}</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/FirewallRulesProperties/product.wxs b/src/test/msi/TestData/FirewallExtensionTests/FirewallRulesProperties/product.wxs
new file mode 100644
index 00000000..1f9935d5
--- /dev/null
+++ b/src/test/msi/TestData/FirewallExtensionTests/FirewallRulesProperties/product.wxs
@@ -0,0 +1,57 @@
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="A1553D10-BEB7-4E60-A0DC-6F1EEE5A1719" Directory="INSTALLFOLDER">
13 <fw:FirewallException
14 Name="WiXToolset Test - 0028" OnUpdate="EnableOnly"
15 Port="[LOCALPORT]"
16 Protocol="[PROTOCOL]"
17 Program="[PROGRAM]"
18 Profile="[PROFILE]"
19 Description="[DESCRIPTION]"
20 Scope="[REMOTESCOPE]"
21 EdgeTraversal="[EDGETRAVERSAL]"
22 Enabled="[ENABLED]"
23 Grouping="[GROUPING]"
24 IcmpTypesAndCodes="[ICMPTYPES]"
25 Interface="[INTERFACE]"
26 InterfaceType="[INTERFACETYPE]"
27 LocalScope="[LOCALSCOPE]"
28 RemotePort="[REMOTEPORT]"
29 Service="[SERVICE]"
30 LocalAppPackageId="[PACKAGEID]"
31 LocalUserAuthorizedList="[LOCALUSERS]"
32 LocalUserOwner="[LOCALOWNER]"
33 RemoteMachineAuthorizedList="[REMOTEMACHINES]"
34 RemoteUserAuthorizedList="[REMOTEUSERS]"
35 IPSecSecureFlags="[SECUREFLAGS]"
36 />
37
38 <fw:FirewallException Name="WiXToolset Test - 0029" OnUpdate="DoNothing" >
39 <fw:RemoteAddress Value="[REMOTEADDRESS]" />
40 <fw:LocalAddress Value="[LOCALADDRESS]" />
41 <fw:InterfaceType Value="[INTERFACETYPE]" />
42 <fw:Interface Name="[INTERFACE]" />
43 </fw:FirewallException>
44
45 <fw:FirewallException Name="WiXToolset Test - 0030" >
46 <fw:RemoteAddress Value="[REMOTEADDRESS1]" />
47 <fw:RemoteAddress Value="[REMOTEADDRESS2]" />
48 <fw:LocalAddress Value="[LOCALADDRESS1]" />
49 <fw:LocalAddress Value="[LOCALADDRESS2]" />
50 <fw:InterfaceType Value="[INTERFACETYPE1]" />
51 <fw:InterfaceType Value="[INTERFACETYPE2]" />
52 <fw:Interface Name="[INTERFACE1]" />
53 <fw:Interface Name="[INTERFACE2]" />
54 </fw:FirewallException>
55 </Component>
56 </Fragment>
57</Wix>
diff --git a/src/test/msi/TestData/FirewallExtensionTests/Module401/Module401.wixproj b/src/test/msi/TestData/FirewallExtensionTests/Module401/Module401.wixproj
new file mode 100644
index 00000000..5f65e657
--- /dev/null
+++ b/src/test/msi/TestData/FirewallExtensionTests/Module401/Module401.wixproj
@@ -0,0 +1,10 @@
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 <OutputType>Module</OutputType>
5 <SuppressSpecificWarnings>1072</SuppressSpecificWarnings>
6 </PropertyGroup>
7 <ItemGroup>
8 <PackageReference Include="WixToolset.Firewall.wixext"/><!--VersionOverride="4.0.1"-->
9 </ItemGroup>
10</Project> \ No newline at end of file
diff --git a/src/test/msi/TestData/FirewallExtensionTests/Module401/data/test.txt b/src/test/msi/TestData/FirewallExtensionTests/Module401/data/test.txt
new file mode 100644
index 00000000..cd0db0e1
--- /dev/null
+++ b/src/test/msi/TestData/FirewallExtensionTests/Module401/data/test.txt
@@ -0,0 +1 @@
This is test.txt. \ No newline at end of file
diff --git a/src/test/msi/TestData/FirewallExtensionTests/Module401/module.wxs b/src/test/msi/TestData/FirewallExtensionTests/Module401/module.wxs
new file mode 100644
index 00000000..872743c7
--- /dev/null
+++ b/src/test/msi/TestData/FirewallExtensionTests/Module401/module.wxs
@@ -0,0 +1,36 @@
1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:fw="http://wixtoolset.org/schemas/v4/wxs/firewall" >
2 <Module Id="MergeModule1" Language="1033" Version="1.0.0.0" Guid="4B2C61BF-59F5-453B-98E3-3389F681EA00">
3 <SummaryInformation Manufacturer="Module 4.0.1 Manufacturer" />
4
5 <Property Id="MODULE401PORT1" Value="40101" />
6 <Property Id="MODULE401PORT2" Value="40102" />
7 <Property Id="MODULE401PORT3" Value="40103" />
8 <Property Id="MODULE401PORT4" Value="40104" />
9
10 <Directory Id="MergeRedirectFolder">
11 <Component Id="ModuleComponent1" Guid="257F9283-1334-423C-A7E7-FEE848BCD37F">
12 <File Id="File1" Name="file1.txt" Source="data/test.txt">
13 <fw:FirewallException Id="FirewallException1"
14 Description="WiX Toolset firewall exception rule integration test - module 401 MergeRedirectFolder - app"
15 Name="WiXToolset401 Test - 0018" Scope="any" Port="[MODULE401PORT1]" />
16 </File>
17 <fw:FirewallException Id="FirewallException2"
18 Description="WiX Toolset firewall exception rule integration test - module 401 MergeRedirectFolder - port"
19 Name="WiXToolset401 Test - 0019" Scope="any" Port="[MODULE401PORT2]" />
20 </Component>
21 </Directory>
22
23 <Directory Id="NotTheMergeRedirectFolder">
24 <Component Id="ModuleComponent2" Guid="48A2D573-0ADB-4010-84E3-96C3D6803E90">
25 <File Id="File2" Name="file2.txt" Source="data/test.txt">
26 <fw:FirewallException Id="FirewallException3"
27 Description="WiX Toolset firewall exception rule integration test - module 401 NotTheMergeRedirectFolder - app"
28 Name="WiXToolset401 Test - 0020" Scope="any" Port="[MODULE401PORT3]" />
29 </File>
30 <fw:FirewallException Id="FirewallException4"
31 Description="WiX Toolset firewall exception rule integration test - module 401 NotTheMergeRedirectFolder - port"
32 Name="WiXToolset401 Test - 0021" Scope="any" Port="[MODULE401PORT4]" />
33 </Component>
34 </Directory>
35 </Module>
36</Wix>
diff --git a/src/test/msi/TestData/FirewallExtensionTests/ModuleCurrent/ModuleCurrent.wixproj b/src/test/msi/TestData/FirewallExtensionTests/ModuleCurrent/ModuleCurrent.wixproj
new file mode 100644
index 00000000..8a84280c
--- /dev/null
+++ b/src/test/msi/TestData/FirewallExtensionTests/ModuleCurrent/ModuleCurrent.wixproj
@@ -0,0 +1,10 @@
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 <OutputType>Module</OutputType>
5 <SuppressSpecificWarnings>1072</SuppressSpecificWarnings>
6 </PropertyGroup>
7 <ItemGroup>
8 <PackageReference Include="WixToolset.Firewall.wixext" />
9 </ItemGroup>
10</Project> \ No newline at end of file
diff --git a/src/test/msi/TestData/FirewallExtensionTests/ModuleCurrent/data/test.txt b/src/test/msi/TestData/FirewallExtensionTests/ModuleCurrent/data/test.txt
new file mode 100644
index 00000000..cd0db0e1
--- /dev/null
+++ b/src/test/msi/TestData/FirewallExtensionTests/ModuleCurrent/data/test.txt
@@ -0,0 +1 @@
This is test.txt. \ No newline at end of file
diff --git a/src/test/msi/TestData/FirewallExtensionTests/ModuleCurrent/module.wxs b/src/test/msi/TestData/FirewallExtensionTests/ModuleCurrent/module.wxs
new file mode 100644
index 00000000..53097acd
--- /dev/null
+++ b/src/test/msi/TestData/FirewallExtensionTests/ModuleCurrent/module.wxs
@@ -0,0 +1,36 @@
1<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:fw="http://wixtoolset.org/schemas/v4/wxs/firewall" >
2 <Module Id="MergeModule1" Language="1033" Version="1.0.0.0" Guid="44FA5DBE-2413-436E-99B3-A0751D6EB420">
3 <SummaryInformation Manufacturer="Example Company - Module Current" />
4
5 <Property Id="MODULECURRENTPORT1" Value="50001" />
6 <Property Id="MODULECURRENTPORT2" Value="50002" />
7 <Property Id="MODULECURRENTPORT3" Value="50003" />
8 <Property Id="MODULECURRENTPORT4" Value="50004" />
9
10 <Directory Id="MergeRedirectFolder">
11 <Component Id="ModuleComponent1" Guid="EB7B8A63-85C4-4ABB-B9DA-33AECAFE38F7">
12 <File Id="File1" Name="file1.txt" Source="data/test.txt">
13 <fw:FirewallException Id="FirewallException1"
14 Description="WiX Toolset firewall exception rule integration test - module MergeRedirectFolder - app"
15 Name="WiXToolset Test - 0022" Scope="any" Port="[MODULECURRENTPORT1]" />
16 </File>
17 <fw:FirewallException Id="FirewallException2"
18 Description="WiX Toolset firewall exception rule integration test - module MergeRedirectFolder - port"
19 Name="WiXToolset Test - 0023" Scope="any" Port="[MODULECURRENTPORT2]" />
20 </Component>
21 </Directory>
22
23 <Directory Id="NotTheMergeRedirectFolder">
24 <Component Id="ModuleComponent2" Guid="0C9DD4FC-5A54-4E96-830D-DDE27B3017B5">
25 <File Id="File2" Name="file2.txt" Source="data/test.txt">
26 <fw:FirewallException Id="FirewallException3"
27 Description="WiX Toolset firewall exception rule integration test - module NotTheMergeRedirectFolder - app"
28 Name="WiXToolset Test - 0024" Scope="any" Port="[MODULECURRENTPORT3]" />
29 </File>
30 <fw:FirewallException Id="FirewallException4"
31 Description="WiX Toolset firewall exception rule integration test - module NotTheMergeRedirectFolder - port"
32 Name="WiXToolset Test - 0025" Scope="any" Port="[MODULECURRENTPORT4]" />
33 </Component>
34 </Directory>
35 </Module>
36</Wix>
diff --git a/src/test/msi/TestData/FirewallExtensionTests/NestedService/NestedService.wixproj b/src/test/msi/TestData/FirewallExtensionTests/NestedService/NestedService.wixproj
new file mode 100644
index 00000000..4a9c9dbd
--- /dev/null
+++ b/src/test/msi/TestData/FirewallExtensionTests/NestedService/NestedService.wixproj
@@ -0,0 +1,14 @@
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>{80635798-F904-4C4E-81D8-27A5106F3998}</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 <PackageReference Include="WixToolset.Util.wixext" />
13 </ItemGroup>
14</Project> \ No newline at end of file
diff --git a/src/test/msi/TestData/FirewallExtensionTests/NestedService/product.wxs b/src/test/msi/TestData/FirewallExtensionTests/NestedService/product.wxs
new file mode 100644
index 00000000..24559a33
--- /dev/null
+++ b/src/test/msi/TestData/FirewallExtensionTests/NestedService/product.wxs
@@ -0,0 +1,25 @@
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" xmlns:util="http://wixtoolset.org/schemas/v4/wxs/util" >
5 <Fragment>
6 <ComponentGroup Id="ProductComponents">
7 <ComponentRef Id="FirewallComponent1"/>
8 </ComponentGroup>
9 </Fragment>
10
11 <Fragment>
12 <Component Id="FirewallComponent1" Guid="FD6E696A-8C42-49BF-B686-0DA5CD4B2C5A" Directory="INSTALLFOLDER" >
13 <fw:FirewallException Id="FirewallException1" Description="WiX Toolset firewall exception rule integration test - service property"
14 Name="WiXToolset Test - 0031" Service="Spooler"/>
15 <util:ServiceConfig ServiceName="Spooler" FirstFailureActionType="restart" SecondFailureActionType="restart" ThirdFailureActionType="none" >
16 <fw:FirewallException Id="FirewallException2" Description="WiX Toolset firewall exception rule integration test - ServiceConfig"
17 Name="WiXToolset Test - 0032" />
18 </util:ServiceConfig>
19 <ServiceInstall Name="WixTestFirewallSrv" Type="ownProcess" Start="disabled" ErrorControl="ignore" Vital="no" Arguments="%WINDIR%\System32\spoolsv.exe" >
20 <fw:FirewallException Id="FirewallException3" Description="WiX Toolset firewall exception rule integration test - ServiceInstall"
21 Name="WiXToolset Test - 0033" />
22 </ServiceInstall>
23 </Component>
24 </Fragment>
25</Wix>
diff --git a/src/test/msi/WixToolsetTest.MsiE2E/FirewallExtensionTests.cs b/src/test/msi/WixToolsetTest.MsiE2E/FirewallExtensionTests.cs
index ce55aa14..380e6f4c 100644
--- a/src/test/msi/WixToolsetTest.MsiE2E/FirewallExtensionTests.cs
+++ b/src/test/msi/WixToolsetTest.MsiE2E/FirewallExtensionTests.cs
@@ -4,6 +4,8 @@ namespace WixToolsetTest.MsiE2E
4{ 4{
5 using System; 5 using System;
6 using System.IO; 6 using System.IO;
7 using System.Linq;
8 using System.Net.NetworkInformation;
7 using NetFwTypeLib; 9 using NetFwTypeLib;
8 using WixTestTools; 10 using WixTestTools;
9 using WixTestTools.Firewall; 11 using WixTestTools.Firewall;
@@ -37,8 +39,8 @@ namespace WixToolsetTest.MsiE2E
37 ApplicationName = this.TestContext.GetTestInstallFolder(false, Path.Combine("FirewallRules", "product.wxs")), 39 ApplicationName = this.TestContext.GetTestInstallFolder(false, Path.Combine("FirewallRules", "product.wxs")),
38 Description = "WiX Toolset firewall exception rule integration test - minimal app properties", 40 Description = "WiX Toolset firewall exception rule integration test - minimal app properties",
39 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN, 41 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
40 EdgeTraversal = true, 42 EdgeTraversal = false,
41 EdgeTraversalOptions = 1, 43 EdgeTraversalOptions = 0,
42 Enabled = true, 44 Enabled = true,
43 InterfaceTypes = "All", 45 InterfaceTypes = "All",
44 LocalAddresses = "*", 46 LocalAddresses = "*",
@@ -124,8 +126,8 @@ namespace WixToolsetTest.MsiE2E
124 ApplicationName = this.TestContext.GetTestInstallFolder(false, Path.Combine("FirewallRules", "product.wxs")), 126 ApplicationName = this.TestContext.GetTestInstallFolder(false, Path.Combine("FirewallRules", "product.wxs")),
125 Description = "WiX Toolset firewall exception rule integration test - minimal app properties", 127 Description = "WiX Toolset firewall exception rule integration test - minimal app properties",
126 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN, 128 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
127 EdgeTraversal = true, 129 EdgeTraversal = false,
128 EdgeTraversalOptions = 1, 130 EdgeTraversalOptions = 0,
129 Enabled = true, 131 Enabled = true,
130 InterfaceTypes = "All", 132 InterfaceTypes = "All",
131 LocalAddresses = "*", 133 LocalAddresses = "*",
@@ -187,8 +189,8 @@ namespace WixToolsetTest.MsiE2E
187 ApplicationName = this.TestContext.GetTestInstallFolder(false, Path.Combine("FirewallRules", "product.wxs")), 189 ApplicationName = this.TestContext.GetTestInstallFolder(false, Path.Combine("FirewallRules", "product.wxs")),
188 Description = "WiX Toolset firewall exception rule integration test - minimal app properties", 190 Description = "WiX Toolset firewall exception rule integration test - minimal app properties",
189 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN, 191 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
190 EdgeTraversal = true, 192 EdgeTraversal = false,
191 EdgeTraversalOptions = 1, 193 EdgeTraversalOptions = 0,
192 Enabled = true, 194 Enabled = true,
193 InterfaceTypes = "All", 195 InterfaceTypes = "All",
194 LocalAddresses = "*", 196 LocalAddresses = "*",
@@ -213,8 +215,8 @@ namespace WixToolsetTest.MsiE2E
213 ApplicationName = this.TestContext.GetTestInstallFolder(false, Path.Combine("DynamicFirewallRules", "product.wxs")), 215 ApplicationName = this.TestContext.GetTestInstallFolder(false, Path.Combine("DynamicFirewallRules", "product.wxs")),
214 Description = "WiX Toolset firewall exception rule integration test - dynamic app description 9999", 216 Description = "WiX Toolset firewall exception rule integration test - dynamic app description 9999",
215 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN, 217 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
216 EdgeTraversal = true, 218 EdgeTraversal = false,
217 EdgeTraversalOptions = 1, 219 EdgeTraversalOptions = 0,
218 Enabled = true, 220 Enabled = true,
219 InterfaceTypes = "All", 221 InterfaceTypes = "All",
220 LocalAddresses = "*", 222 LocalAddresses = "*",
@@ -255,8 +257,8 @@ namespace WixToolsetTest.MsiE2E
255 ApplicationName = Path.Combine(Environment.GetEnvironmentVariable("windir"), "system32", "9999.exe"), 257 ApplicationName = Path.Combine(Environment.GetEnvironmentVariable("windir"), "system32", "9999.exe"),
256 Description = "WiX Toolset firewall exception rule integration test - dynamic Name 9999", 258 Description = "WiX Toolset firewall exception rule integration test - dynamic Name 9999",
257 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN, 259 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
258 EdgeTraversal = true, 260 EdgeTraversal = false,
259 EdgeTraversalOptions = 1, 261 EdgeTraversalOptions = 0,
260 Enabled = true, 262 Enabled = true,
261 InterfaceTypes = "All", 263 InterfaceTypes = "All",
262 LocalAddresses = "*", 264 LocalAddresses = "*",
@@ -285,10 +287,10 @@ namespace WixToolsetTest.MsiE2E
285 var log1 = product.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS); 287 var log1 = product.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
286 288
287 Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0006 pipe")); 289 Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0006 pipe"));
288 Assert.True(LogVerifier.MessageInLogFile(log1, "failed to add app to the authorized apps list")); 290 Assert.True(LogVerifier.MessageInLogFile(log1, "failed to add firewall exception 'WiXToolset401 Test - 0006 pipe' to the list"));
289 291
290 Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0007 pipe")); 292 Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0007 pipe"));
291 Assert.True(LogVerifier.MessageInLogFile(log1, "failed to add app to the authorized ports list")); 293 Assert.True(LogVerifier.MessageInLogFile(log1, "failed to add firewall exception 'WiXToolset401 Test - 0007 pipe' to the list"));
292 294
293 var expected = new RuleDetails("WiXToolset401 Test - 0008 removal") 295 var expected = new RuleDetails("WiXToolset401 Test - 0008 removal")
294 { 296 {
@@ -296,8 +298,8 @@ namespace WixToolsetTest.MsiE2E
296 ApplicationName = "test.exe", 298 ApplicationName = "test.exe",
297 Description = "WiX Toolset firewall exception rule integration test - removal test", 299 Description = "WiX Toolset firewall exception rule integration test - removal test",
298 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN, 300 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
299 EdgeTraversal = true, 301 EdgeTraversal = false,
300 EdgeTraversalOptions = 1, 302 EdgeTraversalOptions = 0,
301 Enabled = true, 303 Enabled = true,
302 InterfaceTypes = "All", 304 InterfaceTypes = "All",
303 LocalPorts = "52390", 305 LocalPorts = "52390",
@@ -313,7 +315,7 @@ namespace WixToolsetTest.MsiE2E
313 Verifier.RemoveFirewallRuleByName("WiXToolset401 Test - 0008 removal"); 315 Verifier.RemoveFirewallRuleByName("WiXToolset401 Test - 0008 removal");
314 316
315 var log2 = product.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS, "NORULENAME=1"); 317 var log2 = product.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS, "NORULENAME=1");
316 Assert.True(LogVerifier.MessageInLogFile(log2, "failed to remove firewall rule")); 318 Assert.True(LogVerifier.MessageInLogFile(log2, "failed to remove firewall exception for name"));
317 } 319 }
318 320
319 [RuntimeFact] 321 [RuntimeFact]
@@ -370,8 +372,8 @@ namespace WixToolsetTest.MsiE2E
370 ApplicationName = "test.exe", 372 ApplicationName = "test.exe",
371 Description = "WiX Toolset firewall exception rule integration test - ports can only be specified if protocol is TCP or UDP", 373 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, 374 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
373 EdgeTraversal = true, 375 EdgeTraversal = false,
374 EdgeTraversalOptions = 1, 376 EdgeTraversalOptions = 0,
375 Enabled = true, 377 Enabled = true,
376 InterfaceTypes = "All", 378 InterfaceTypes = "All",
377 LocalAddresses = "*", 379 LocalAddresses = "*",
@@ -532,5 +534,609 @@ namespace WixToolsetTest.MsiE2E
532 Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0016")); 534 Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0016"));
533 Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0017")); 535 Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0017"));
534 } 536 }
537
538 [RuntimeFact]
539 public void CanInstallAndUninstallFirewallRulesWithInterfaces()
540 {
541 var names = NetworkInterface.GetAllNetworkInterfaces()
542 .Take(3)
543 .Select(ni => ni.Name);
544
545 var props = names.Select((name, idx) => $"INTERFACE{idx + 1}=\"{name}\"")
546 .Concat(new[] { "INTERFACETYPE=Lan" }).ToArray();
547
548 var product = this.CreatePackageInstaller("FirewallRulesInterfaces");
549 product.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS, props);
550
551 var expected1 = new RuleDetails("WiXToolset500 Test - 0028")
552 {
553 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
554 ApplicationName = this.TestContext.GetTestInstallFolder(false, Path.Combine("FirewallRulesInterfaces", "product.wxs")),
555 Description = "WiX Toolset firewall exception rule integration test - three interfaces",
556 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
557 EdgeTraversal = false,
558 EdgeTraversalOptions = 0,
559 Enabled = true,
560 InterfaceTypes = "Lan,Wireless,RemoteAccess",
561 Interfaces = names.ToArray<object>(),
562 LocalAddresses = "*",
563 Profiles = Int32.MaxValue,
564 Protocol = 256,
565 RemoteAddresses = "*",
566 SecureFlags = 0,
567 };
568
569 Verifier.VerifyFirewallRule("WiXToolset500 Test - 0028", expected1);
570
571 var expected2 = new RuleDetails("WiXToolset500 Test - 0029")
572 {
573 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
574 Description = "WiX Toolset firewall exception rule integration test - one interface",
575 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
576 EdgeTraversal = false,
577 EdgeTraversalOptions = 0,
578 Enabled = true,
579 InterfaceTypes = "Lan",
580 Interfaces = names.Take(1).ToArray<object>(),
581 LocalAddresses = "*",
582 LocalPorts = "29292",
583 Profiles = Int32.MaxValue,
584 Protocol = 6,
585 RemoteAddresses = "*",
586 RemotePorts = "*",
587 SecureFlags = 0,
588 };
589
590 Verifier.VerifyFirewallRule("WiXToolset500 Test - 0029", expected2);
591
592 props = names.Take(1).Select((name, idx) => $"INTERFACE{idx + 2}=\"{name}\"").ToArray();
593
594 product.RepairProduct(MSIExec.MSIExecReturnCode.SUCCESS, props);
595
596 var expected3 = new RuleDetails("WiXToolset500 Test - 0028")
597 {
598 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
599 ApplicationName = this.TestContext.GetTestInstallFolder(false, Path.Combine("FirewallRulesInterfaces", "product.wxs")),
600 Description = "WiX Toolset firewall exception rule integration test - three interfaces",
601 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
602 EdgeTraversal = false,
603 EdgeTraversalOptions = 0,
604 Enabled = true,
605 InterfaceTypes = "Lan,Wireless,RemoteAccess",
606 Interfaces = names.Take(1).ToArray<object>(),
607 LocalAddresses = "*",
608 Profiles = Int32.MaxValue,
609 Protocol = 256,
610 RemoteAddresses = "*",
611 SecureFlags = 0,
612 };
613
614 Verifier.VerifyFirewallRule("WiXToolset500 Test - 0028", expected3);
615
616 var expected4 = new RuleDetails("WiXToolset500 Test - 0029")
617 {
618 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
619 Description = "WiX Toolset firewall exception rule integration test - one interface",
620 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
621 EdgeTraversal = false,
622 EdgeTraversalOptions = 0,
623 Enabled = true,
624 InterfaceTypes = "All",
625 LocalAddresses = "*",
626 LocalPorts = "29292",
627 Profiles = Int32.MaxValue,
628 Protocol = 6,
629 RemoteAddresses = "*",
630 RemotePorts = "*",
631 SecureFlags = 0,
632 };
633
634 Verifier.VerifyFirewallRule("WiXToolset500 Test - 0029", expected4);
635
636 product.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
637
638 // verify the firewall exceptions have been removed.
639 Assert.False(Verifier.FirewallRuleExists("WiXToolset500 Test - 0028"));
640 Assert.False(Verifier.FirewallRuleExists("WiXToolset500 Test - 0029"));
641 }
642
643 [RuntimeFact]
644 public void CanInstallAndUninstallFirewallRulesPackagedByDifferentModules()
645 {
646 var product = this.CreatePackageInstaller("CrossVersionMerge");
647 product.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
648
649 // Validate new firewall exception details.
650 var expected1 = new RuleDetails("WiXToolset401 Test - 0018")
651 {
652 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
653 ApplicationName = Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles(x86)"), "MsiPackage", "file1.txt"),
654 Description = "WiX Toolset firewall exception rule integration test - module 401 MergeRedirectFolder - app",
655 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
656 EdgeTraversal = true,
657 EdgeTraversalOptions = 1,
658 Enabled = true,
659 InterfaceTypes = "All",
660 LocalAddresses = "*",
661 LocalPorts = "40101",
662 Profiles = Int32.MaxValue,
663 Protocol = 6,
664 RemoteAddresses = "*",
665 RemotePorts = "*",
666 SecureFlags = 0,
667 };
668
669 Verifier.VerifyFirewallRule("WiXToolset401 Test - 0018", expected1);
670
671 var expected2 = new RuleDetails("WiXToolset401 Test - 0019")
672 {
673 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
674 Description = "WiX Toolset firewall exception rule integration test - module 401 MergeRedirectFolder - port",
675 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
676 EdgeTraversal = false,
677 EdgeTraversalOptions = 0,
678 Enabled = true,
679 InterfaceTypes = "All",
680 LocalAddresses = "*",
681 LocalPorts = "40102",
682 Profiles = Int32.MaxValue,
683 Protocol = 6,
684 RemoteAddresses = "*",
685 RemotePorts = "*",
686 SecureFlags = 0,
687 };
688
689 Verifier.VerifyFirewallRule("WiXToolset401 Test - 0019", expected2);
690
691 var expected3 = new RuleDetails("WiXToolset401 Test - 0020")
692 {
693 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
694 ApplicationName = Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles(x86)"), "MsiPackage", "file2.txt"),
695 Description = "WiX Toolset firewall exception rule integration test - module 401 NotTheMergeRedirectFolder - app",
696 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
697 EdgeTraversal = true,
698 EdgeTraversalOptions = 1,
699 Enabled = true,
700 InterfaceTypes = "All",
701 LocalAddresses = "*",
702 LocalPorts = "40103",
703 Profiles = Int32.MaxValue,
704 Protocol = 6,
705 RemoteAddresses = "*",
706 RemotePorts = "*",
707 SecureFlags = 0,
708 };
709
710 Verifier.VerifyFirewallRule("WiXToolset401 Test - 0020", expected3);
711
712 var expected4 = new RuleDetails("WiXToolset401 Test - 0021")
713 {
714 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
715 Description = "WiX Toolset firewall exception rule integration test - module 401 NotTheMergeRedirectFolder - port",
716 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
717 EdgeTraversal = false,
718 EdgeTraversalOptions = 0,
719 Enabled = true,
720 InterfaceTypes = "All",
721 LocalAddresses = "*",
722 LocalPorts = "40104",
723 Profiles = Int32.MaxValue,
724 Protocol = 6,
725 RemoteAddresses = "*",
726 RemotePorts = "*",
727 SecureFlags = 0,
728 };
729
730 Verifier.VerifyFirewallRule("WiXToolset401 Test - 0021", expected4);
731
732 var expected5 = new RuleDetails("WiXToolset Test - 0022")
733 {
734 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
735 ApplicationName = Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles(x86)"), "MsiPackage", "file1.txt"),
736 Description = "WiX Toolset firewall exception rule integration test - module MergeRedirectFolder - app",
737 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
738 EdgeTraversal = false,
739 EdgeTraversalOptions = 0,
740 Enabled = true,
741 InterfaceTypes = "All",
742 LocalAddresses = "*",
743 LocalPorts = "50001",
744 Profiles = Int32.MaxValue,
745 Protocol = 6,
746 RemoteAddresses = "*",
747 RemotePorts = "*",
748 SecureFlags = 0,
749 };
750
751 Verifier.VerifyFirewallRule("WiXToolset Test - 0022", expected5);
752
753 var expected6 = new RuleDetails("WiXToolset Test - 0023")
754 {
755 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
756 Description = "WiX Toolset firewall exception rule integration test - module MergeRedirectFolder - port",
757 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
758 EdgeTraversal = false,
759 EdgeTraversalOptions = 0,
760 Enabled = true,
761 InterfaceTypes = "All",
762 LocalAddresses = "*",
763 LocalPorts = "50002",
764 Profiles = Int32.MaxValue,
765 Protocol = 6,
766 RemoteAddresses = "*",
767 RemotePorts = "*",
768 SecureFlags = 0,
769 };
770
771 Verifier.VerifyFirewallRule("WiXToolset Test - 0023", expected6);
772
773 var expected7 = new RuleDetails("WiXToolset Test - 0024")
774 {
775 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
776 ApplicationName = Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles(x86)"), "MsiPackage", "file2.txt"),
777 Description = "WiX Toolset firewall exception rule integration test - module NotTheMergeRedirectFolder - app",
778 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
779 EdgeTraversal = false,
780 EdgeTraversalOptions = 0,
781 Enabled = true,
782 InterfaceTypes = "All",
783 LocalAddresses = "*",
784 LocalPorts = "50003",
785 Profiles = Int32.MaxValue,
786 Protocol = 6,
787 RemoteAddresses = "*",
788 RemotePorts = "*",
789 SecureFlags = 0,
790 };
791
792 Verifier.VerifyFirewallRule("WiXToolset Test - 0024", expected7);
793
794 var expected8 = new RuleDetails("WiXToolset Test - 0025")
795 {
796 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
797 Description = "WiX Toolset firewall exception rule integration test - module NotTheMergeRedirectFolder - port",
798 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
799 EdgeTraversal = false,
800 EdgeTraversalOptions = 0,
801 Enabled = true,
802 InterfaceTypes = "All",
803 LocalAddresses = "*",
804 LocalPorts = "50004",
805 Profiles = Int32.MaxValue,
806 Protocol = 6,
807 RemoteAddresses = "*",
808 RemotePorts = "*",
809 SecureFlags = 0,
810 };
811
812 Verifier.VerifyFirewallRule("WiXToolset Test - 0025", expected8);
813
814 var expected9 = new RuleDetails("WiXToolset Test - 0026")
815 {
816 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
817 ApplicationName = Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles(x86)"), "MsiPackage", "package.wxs"),
818 Description = "WiX Toolset firewall exception rule integration test - package app",
819 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
820 EdgeTraversal = false,
821 EdgeTraversalOptions = 0,
822 Enabled = true,
823 InterfaceTypes = "All",
824 LocalAddresses = "*",
825 LocalPorts = "20001",
826 Profiles = Int32.MaxValue,
827 Protocol = 6,
828 RemoteAddresses = "*",
829 RemotePorts = "*",
830 SecureFlags = 0,
831 };
832
833 Verifier.VerifyFirewallRule("WiXToolset Test - 0026", expected9);
834
835 var expected10 = new RuleDetails("WiXToolset Test - 0027")
836 {
837 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
838 Description = "WiX Toolset firewall exception rule integration test - package port",
839 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
840 EdgeTraversal = false,
841 EdgeTraversalOptions = 0,
842 Enabled = true,
843 InterfaceTypes = "All",
844 LocalAddresses = "*",
845 LocalPorts = "20002",
846 Profiles = Int32.MaxValue,
847 Protocol = 6,
848 RemoteAddresses = "*",
849 RemotePorts = "*",
850 SecureFlags = 0,
851 };
852
853 Verifier.VerifyFirewallRule("WiXToolset Test - 0027", expected10);
854
855 product.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
856
857 // verify the firewall exceptions have been removed.
858 Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0018"));
859 Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0019"));
860 Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0020"));
861 Assert.False(Verifier.FirewallRuleExists("WiXToolset401 Test - 0021"));
862 Assert.False(Verifier.FirewallRuleExists("WiXToolset Test - 0022"));
863 Assert.False(Verifier.FirewallRuleExists("WiXToolset Test - 0023"));
864 Assert.False(Verifier.FirewallRuleExists("WiXToolset Test - 0024"));
865 Assert.False(Verifier.FirewallRuleExists("WiXToolset Test - 0025"));
866 Assert.False(Verifier.FirewallRuleExists("WiXToolset Test - 0026"));
867 Assert.False(Verifier.FirewallRuleExists("WiXToolset Test - 0027"));
868 }
869
870 [RuntimeFact]
871 public void ServiceNameIsPassedIntoNestedRules()
872 {
873 var product = this.CreatePackageInstaller("NestedService");
874 product.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
875
876 var expected1 = new RuleDetails("WiXToolset Test - 0031")
877 {
878 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
879 Protocol = 256,
880 LocalAddresses = "*",
881 RemoteAddresses = "*",
882 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
883 Description = "WiX Toolset firewall exception rule integration test - service property",
884 EdgeTraversal = false,
885 EdgeTraversalOptions = 0,
886 Enabled = true,
887 InterfaceTypes = "All",
888 Profiles = Int32.MaxValue,
889 SecureFlags = 0,
890 ServiceName = "Spooler",
891 };
892
893 Verifier.VerifyFirewallRule("WiXToolset Test - 0031", expected1);
894
895 var expected2 = new RuleDetails("WiXToolset Test - 0032")
896 {
897 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
898 Protocol = 256,
899 LocalAddresses = "*",
900 RemoteAddresses = "*",
901 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
902 Description = "WiX Toolset firewall exception rule integration test - ServiceConfig",
903 EdgeTraversal = false,
904 EdgeTraversalOptions = 0,
905 Enabled = true,
906 InterfaceTypes = "All",
907 Profiles = Int32.MaxValue,
908 SecureFlags = 0,
909 ServiceName = "Spooler",
910 };
911
912 Verifier.VerifyFirewallRule("WiXToolset Test - 0032", expected2);
913
914 var expected3 = new RuleDetails("WiXToolset Test - 0033")
915 {
916 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
917 Protocol = 256,
918 LocalAddresses = "*",
919 RemoteAddresses = "*",
920 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
921 Description = "WiX Toolset firewall exception rule integration test - ServiceInstall",
922 EdgeTraversal = false,
923 EdgeTraversalOptions = 0,
924 Enabled = true,
925 InterfaceTypes = "All",
926 Profiles = Int32.MaxValue,
927 SecureFlags = 0,
928 ServiceName = "WixTestFirewallSrv",
929 };
930
931 Verifier.VerifyFirewallRule("WiXToolset Test - 0033", expected3);
932
933 product.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
934
935 // verify the firewall exceptions have been removed.
936 Assert.False(Verifier.FirewallRuleExists("WiXToolset Test - 0031"));
937 Assert.False(Verifier.FirewallRuleExists("WiXToolset Test - 0032"));
938 Assert.False(Verifier.FirewallRuleExists("WiXToolset Test - 0033"));
939 }
940
941 [RuntimeFact]
942 public void SucceedWhenEnableOnlyFlagIsSet()
943 {
944 var product = this.CreatePackageInstaller("FirewallRulesProperties");
945 product.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
946
947 var expected1 = new RuleDetails("WiXToolset Test - 0028")
948 {
949 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
950 Protocol = 256,
951 LocalAddresses = "*",
952 RemoteAddresses = "*",
953 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
954 EdgeTraversal = false,
955 EdgeTraversalOptions = 0,
956 Enabled = true,
957 InterfaceTypes = "All",
958 Profiles = Int32.MaxValue,
959 SecureFlags = 0,
960 };
961
962 Verifier.VerifyFirewallRule("WiXToolset Test - 0028", expected1);
963
964 Verifier.DisableFirewallRule("WiXToolset Test - 0028");
965
966 var args = new[]
967 {
968 "LOCALPORT=3456",
969 "PROTOCOL=6",
970 "PROGRAM=ShouldBeUnchanged",
971 "PROFILE=2",
972 "DESCRIPTION=ShouldBeUnchanged",
973 "REMOTESCOPE=ShouldBeUnchanged",
974 "EDGETRAVERSAL=3",
975 "ENABLED=1",
976 "GROUPING=ShouldBeUnchanged",
977 "ICMPTYPES=ShouldBeUnchanged",
978 "INTERFACE=ShouldBeUnchanged",
979 "INTERFACETYPE=ShouldBeUnchanged",
980 "LOCALSCOPE=ShouldBeUnchanged",
981 "REMOTEPORT=60000",
982 "SERVICE=ShouldBeUnchanged",
983 "PACKAGEID=ShouldBeUnchanged",
984 "LOCALUSERS=ShouldBeUnchanged",
985 "LOCALOWNER=ShouldBeUnchanged",
986 "REMOTEMACHINES=ShouldBeUnchanged",
987 "REMOTEUSERS=ShouldBeUnchanged",
988 "SECUREFLAGS=15",
989 "REMOTEADDRESS=ShouldBeUnchanged",
990 "LOCALADDRESS=ShouldBeUnchanged",
991 };
992
993 product.RepairProduct(MSIExec.MSIExecReturnCode.SUCCESS, args);
994
995 var expected2 = new RuleDetails("WiXToolset Test - 0028")
996 {
997 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
998 Protocol = 256,
999 LocalAddresses = "*",
1000 RemoteAddresses = "*",
1001 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
1002 EdgeTraversal = false,
1003 EdgeTraversalOptions = 0,
1004 Enabled = true,
1005 InterfaceTypes = "All",
1006 Profiles = Int32.MaxValue,
1007 SecureFlags = 0,
1008 };
1009
1010 Verifier.VerifyFirewallRule("WiXToolset Test - 0028", expected2);
1011
1012 product.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
1013
1014 // verify the firewall exceptions have been removed.
1015 Assert.False(Verifier.FirewallRuleExists("WiXToolset Test - 0028"));
1016 }
1017
1018 [RuntimeFact]
1019 public void SucceedWhenDoNothingFlagIsSet()
1020 {
1021 var product = this.CreatePackageInstaller("FirewallRulesProperties");
1022 product.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
1023
1024 var expected1 = new RuleDetails("WiXToolset Test - 0029")
1025 {
1026 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
1027 Protocol = 256,
1028 LocalAddresses = "*",
1029 RemoteAddresses = "*",
1030 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
1031 EdgeTraversal = false,
1032 EdgeTraversalOptions = 0,
1033 Enabled = true,
1034 InterfaceTypes = "All",
1035 Profiles = Int32.MaxValue,
1036 SecureFlags = 0,
1037 };
1038
1039 Verifier.VerifyFirewallRule("WiXToolset Test - 0029", expected1);
1040 Verifier.DisableFirewallRule("WiXToolset Test - 0029");
1041
1042 var args = new[]
1043 {
1044 "INTERFACE=ShouldBeUnchanged",
1045 "INTERFACETYPE=ShouldBeUnchanged",
1046 "REMOTEADDRESS=ShouldBeUnchanged",
1047 "LOCALADDRESS=ShouldBeUnchanged",
1048 };
1049
1050 product.RepairProduct(MSIExec.MSIExecReturnCode.SUCCESS, args);
1051
1052 var expected2 = new RuleDetails("WiXToolset Test - 0029")
1053 {
1054 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
1055 Protocol = 256,
1056 LocalAddresses = "*",
1057 RemoteAddresses = "*",
1058 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
1059 EdgeTraversal = false,
1060 EdgeTraversalOptions = 0,
1061 Enabled = false, // remains as disabled after the repair
1062 InterfaceTypes = "All",
1063 Profiles = Int32.MaxValue,
1064 SecureFlags = 0,
1065 };
1066
1067 Verifier.VerifyFirewallRule("WiXToolset Test - 0029", expected2);
1068
1069 product.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
1070
1071 // verify the firewall exceptions have been removed.
1072 Assert.False(Verifier.FirewallRuleExists("WiXToolset Test - 0029"));
1073 }
1074
1075 [RuntimeFact]
1076 public void SucceedWhenNoFlagIsSet()
1077 {
1078 var product = this.CreatePackageInstaller("FirewallRulesProperties");
1079 product.InstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
1080
1081 var expected1 = new RuleDetails("WiXToolset Test - 0030")
1082 {
1083 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
1084 Protocol = 256,
1085 LocalAddresses = "*",
1086 RemoteAddresses = "*",
1087 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
1088 EdgeTraversal = false,
1089 EdgeTraversalOptions = 0,
1090 Enabled = true,
1091 InterfaceTypes = "All",
1092 Profiles = Int32.MaxValue,
1093 SecureFlags = 0,
1094 };
1095
1096 Verifier.VerifyFirewallRule("WiXToolset Test - 0030", expected1);
1097 Verifier.DisableFirewallRule("WiXToolset Test - 0030");
1098
1099 var names = NetworkInterface.GetAllNetworkInterfaces()
1100 .Take(2)
1101 .Select(ni => ni.Name);
1102
1103 var args = names.Select((name, idx) => $"INTERFACE{idx + 1}=\"{name}\"")
1104 .Concat(new[]
1105 {
1106 "INTERFACETYPE1=Wireless",
1107 "INTERFACETYPE2=Lan",
1108 "REMOTEADDRESS1=DHCP",
1109 "REMOTEADDRESS2=LocalSubnet",
1110 "LOCALADDRESS1=127.0.0.1",
1111 "LOCALADDRESS2=192.168.1.1",
1112 })
1113 .ToArray();
1114
1115 product.RepairProduct(MSIExec.MSIExecReturnCode.SUCCESS, args);
1116
1117 var expected2 = new RuleDetails("WiXToolset Test - 0030")
1118 {
1119 Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW,
1120 Protocol = 256,
1121 LocalAddresses = "127.0.0.1/255.255.255.255,192.168.1.1/255.255.255.255",
1122 RemoteAddresses = "LocalSubnet,DHCP",
1123 Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN,
1124 Description = "",
1125 EdgeTraversal = false,
1126 EdgeTraversalOptions = 0,
1127 Enabled = true,
1128 Interfaces = names.ToArray(),
1129 InterfaceTypes = "Lan,Wireless",
1130 Profiles = Int32.MaxValue,
1131 SecureFlags = 0,
1132 };
1133
1134 Verifier.VerifyFirewallRule("WiXToolset Test - 0030", expected2);
1135
1136 product.UninstallProduct(MSIExec.MSIExecReturnCode.SUCCESS);
1137
1138 // verify the firewall exceptions have been removed.
1139 Assert.False(Verifier.FirewallRuleExists("WiXToolset Test - 0030"));
1140 }
535 } 1141 }
536} 1142}
diff --git a/src/test/msi/WixToolsetTest.MsiE2E/WixToolsetTest.MsiE2E.csproj b/src/test/msi/WixToolsetTest.MsiE2E/WixToolsetTest.MsiE2E.csproj
index a5536de4..7d4695d3 100644
--- a/src/test/msi/WixToolsetTest.MsiE2E/WixToolsetTest.MsiE2E.csproj
+++ b/src/test/msi/WixToolsetTest.MsiE2E/WixToolsetTest.MsiE2E.csproj
@@ -29,6 +29,7 @@
29 29
30 <ItemGroup> 30 <ItemGroup>
31 <PackageReference Include="Microsoft.Win32.Registry" /> 31 <PackageReference Include="Microsoft.Win32.Registry" />
32 <PackageReference Include="System.Net.NetworkInformation" />
32 <PackageReference Include="System.Security.Principal.Windows" /> 33 <PackageReference Include="System.Security.Principal.Windows" />
33 <PackageReference Include="WixInternal.TestSupport" /> 34 <PackageReference Include="WixInternal.TestSupport" />
34 <PackageReference Include="WixToolset.Data" /> 35 <PackageReference Include="WixToolset.Data" />