aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ca/firewall.cpp46
-rw-r--r--src/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs17
-rw-r--r--src/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/Package.en-us.wxl11
-rw-r--r--src/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/Package.wxs22
-rw-r--r--src/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/PackageComponents.wxs14
-rw-r--r--src/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/example.txt1
-rw-r--r--src/test/WixToolsetTest.Firewall/WixToolsetTest.Firewall.csproj4
-rw-r--r--src/wixext/FirewallCompiler.cs7
-rw-r--r--src/wixext/FirewallConstants.cs2
-rw-r--r--src/wixext/FirewallDecompiler.cs13
-rw-r--r--src/wixext/FirewallTableDefinitions.cs1
-rw-r--r--src/wixext/Tuples/WixFirewallExceptionTuple.cs8
-rw-r--r--src/wixext/firewall.xsd10
-rw-r--r--src/wixlib/firewall.wixproj4
-rw-r--r--src/wixlib/packages.config2
15 files changed, 142 insertions, 20 deletions
diff --git a/src/ca/firewall.cpp b/src/ca/firewall.cpp
index 62a5b454..bf40ce77 100644
--- a/src/ca/firewall.cpp
+++ b/src/ca/firewall.cpp
@@ -3,7 +3,7 @@
3#include "precomp.h" 3#include "precomp.h"
4 4
5LPCWSTR vcsFirewallExceptionQuery = 5LPCWSTR vcsFirewallExceptionQuery =
6 L"SELECT `Name`, `RemoteAddresses`, `Port`, `Protocol`, `Program`, `Attributes`, `Profile`, `Component_`, `Description` FROM `WixFirewallException`"; 6 L"SELECT `Name`, `RemoteAddresses`, `Port`, `Protocol`, `Program`, `Attributes`, `Profile`, `Component_`, `Description`, `Direction` FROM `WixFirewallException`";
7enum eFirewallExceptionQuery { feqName = 1, feqRemoteAddresses, feqPort, feqProtocol, feqProgram, feqAttributes, feqProfile, feqComponent, feqDescription }; 7enum eFirewallExceptionQuery { feqName = 1, feqRemoteAddresses, feqPort, feqProtocol, feqProgram, feqAttributes, feqProfile, feqComponent, feqDescription };
8enum eFirewallExceptionTarget { fetPort = 1, fetApplication, fetUnknown }; 8enum eFirewallExceptionTarget { fetPort = 1, fetApplication, fetUnknown };
9enum eFirewallExceptionAttributes { feaIgnoreFailures = 1 }; 9enum eFirewallExceptionAttributes { feaIgnoreFailures = 1 };
@@ -36,6 +36,7 @@ static UINT SchedFirewallExceptions(
36 LPWSTR pwzComponent = NULL; 36 LPWSTR pwzComponent = NULL;
37 LPWSTR pwzFormattedFile = NULL; 37 LPWSTR pwzFormattedFile = NULL;
38 LPWSTR pwzDescription = NULL; 38 LPWSTR pwzDescription = NULL;
39 int iDirection = 0;
39 40
40 // initialize 41 // initialize
41 hr = WcaInitialize(hInstall, "SchedFirewallExceptions"); 42 hr = WcaInitialize(hInstall, "SchedFirewallExceptions");
@@ -130,6 +131,9 @@ static UINT SchedFirewallExceptions(
130 131
131 hr = WcaWriteStringToCaData(pwzDescription, &pwzCustomActionData); 132 hr = WcaWriteStringToCaData(pwzDescription, &pwzCustomActionData);
132 ExitOnFailure(hr, "failed to write firewall rule description to custom action data"); 133 ExitOnFailure(hr, "failed to write firewall rule description to custom action data");
134
135 hr = WcaWriteIntegerToCaData(iDirection, &pwzCustomActionData);
136 ExitOnFailure(hr, "failed to write firewall rule direction to custom action data");
133 } 137 }
134 138
135 // reaching the end of the list is actually a good thing, not an error 139 // reaching the end of the list is actually a good thing, not an error
@@ -270,6 +274,7 @@ static HRESULT CreateFwRuleObject(
270 __in LPCWSTR wzPort, 274 __in LPCWSTR wzPort,
271 __in int iProtocol, 275 __in int iProtocol,
272 __in LPCWSTR wzDescription, 276 __in LPCWSTR wzDescription,
277 __in int iDirection,
273 __out INetFwRule** ppNetFwRule 278 __out INetFwRule** ppNetFwRule
274 ) 279 )
275{ 280{
@@ -321,6 +326,12 @@ static HRESULT CreateFwRuleObject(
321 ExitOnFailure(hr, "failed to set exception description '%ls'", bstrDescription); 326 ExitOnFailure(hr, "failed to set exception description '%ls'", bstrDescription);
322 } 327 }
323 328
329 if (MSI_NULL_INTEGER != iDirection)
330 {
331 hr = pNetFwRule->put_Direction(static_cast<NET_FW_RULE_DIRECTION> (iDirection));
332 ExitOnFailure(hr, "failed to set exception direction");
333 }
334
324 *ppNetFwRule = pNetFwRule; 335 *ppNetFwRule = pNetFwRule;
325 pNetFwRule = NULL; 336 pNetFwRule = NULL;
326 337
@@ -429,7 +440,8 @@ static HRESULT AddApplicationException(
429 __in BOOL fIgnoreFailures, 440 __in BOOL fIgnoreFailures,
430 __in LPCWSTR wzPort, 441 __in LPCWSTR wzPort,
431 __in int iProtocol, 442 __in int iProtocol,
432 __in LPCWSTR wzDescription 443 __in LPCWSTR wzDescription,
444 __in int iDirection
433 ) 445 )
434{ 446{
435 HRESULT hr = S_OK; 447 HRESULT hr = S_OK;
@@ -456,7 +468,7 @@ static HRESULT AddApplicationException(
456 hr = pNetFwRules->Item(bstrName, &pNetFwRule); 468 hr = pNetFwRules->Item(bstrName, &pNetFwRule);
457 if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) 469 if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
458 { 470 {
459 hr = CreateFwRuleObject(bstrName, iProfile, wzRemoteAddresses, wzPort, iProtocol, wzDescription, &pNetFwRule); 471 hr = CreateFwRuleObject(bstrName, iProfile, wzRemoteAddresses, wzPort, iProtocol, wzDescription, iDirection, &pNetFwRule);
460 ExitOnFailure(hr, "failed to create FwRule object"); 472 ExitOnFailure(hr, "failed to create FwRule object");
461 473
462 // set edge traversal to true 474 // set edge traversal to true
@@ -590,8 +602,9 @@ static HRESULT AddPortException(
590 __in BOOL fIgnoreFailures, 602 __in BOOL fIgnoreFailures,
591 __in LPCWSTR wzPort, 603 __in LPCWSTR wzPort,
592 __in int iProtocol, 604 __in int iProtocol,
593 __in LPCWSTR wzDescription 605 __in LPCWSTR wzDescription,
594 ) 606 __in int iDirection
607)
595{ 608{
596 HRESULT hr = S_OK; 609 HRESULT hr = S_OK;
597 BSTR bstrName = NULL; 610 BSTR bstrName = NULL;
@@ -614,7 +627,7 @@ static HRESULT AddPortException(
614 hr = pNetFwRules->Item(bstrName, &pNetFwRule); 627 hr = pNetFwRules->Item(bstrName, &pNetFwRule);
615 if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) 628 if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
616 { 629 {
617 hr = CreateFwRuleObject(bstrName, iProfile, wzRemoteAddresses, wzPort, iProtocol, wzDescription, &pNetFwRule); 630 hr = CreateFwRuleObject(bstrName, iProfile, wzRemoteAddresses, wzPort, iProtocol, wzDescription, iDirection, &pNetFwRule);
618 ExitOnFailure(hr, "failed to create FwRule object"); 631 ExitOnFailure(hr, "failed to create FwRule object");
619 632
620 // enable it 633 // enable it
@@ -825,14 +838,15 @@ static HRESULT AddApplicationException(
825 __in BOOL fIgnoreFailures, 838 __in BOOL fIgnoreFailures,
826 __in LPCWSTR wzPort, 839 __in LPCWSTR wzPort,
827 __in int iProtocol, 840 __in int iProtocol,
828 __in LPCWSTR wzDescription 841 __in LPCWSTR wzDescription,
829 ) 842 __in int iDirection
843)
830{ 844{
831 HRESULT hr = S_OK; 845 HRESULT hr = S_OK;
832 846
833 if (fSupportProfiles) 847 if (fSupportProfiles)
834 { 848 {
835 hr = AddApplicationException(wzFile, wzName, iProfile, wzRemoteAddresses, fIgnoreFailures, wzPort, iProtocol, wzDescription); 849 hr = AddApplicationException(wzFile, wzName, iProfile, wzRemoteAddresses, fIgnoreFailures, wzPort, iProtocol, wzDescription, iDirection);
836 } 850 }
837 else 851 else
838 { 852 {
@@ -860,14 +874,15 @@ static HRESULT AddPortException(
860 __in BOOL fIgnoreFailures, 874 __in BOOL fIgnoreFailures,
861 __in LPCWSTR wzPort, 875 __in LPCWSTR wzPort,
862 __in int iProtocol, 876 __in int iProtocol,
863 __in LPCWSTR wzDescription 877 __in LPCWSTR wzDescription,
864 ) 878 __in int iDirection
879)
865{ 880{
866 HRESULT hr = S_OK; 881 HRESULT hr = S_OK;
867 882
868 if (fSupportProfiles) 883 if (fSupportProfiles)
869 { 884 {
870 hr = AddPortException(wzName, iProfile, wzRemoteAddresses, fIgnoreFailures, wzPort, iProtocol, wzDescription); 885 hr = AddPortException(wzName, iProfile, wzRemoteAddresses, fIgnoreFailures, wzPort, iProtocol, wzDescription, iDirection);
871 } 886 }
872 else 887 else
873 { 888 {
@@ -951,6 +966,7 @@ extern "C" UINT __stdcall ExecFirewallExceptions(
951 LPWSTR pwzDescription = NULL; 966 LPWSTR pwzDescription = NULL;
952 int iProtocol = 0; 967 int iProtocol = 0;
953 int iProfile = 0; 968 int iProfile = 0;
969 int iDirection = 0;
954 970
955 // initialize 971 // initialize
956 hr = WcaInitialize(hInstall, "ExecFirewallExceptions"); 972 hr = WcaInitialize(hInstall, "ExecFirewallExceptions");
@@ -1013,6 +1029,8 @@ extern "C" UINT __stdcall ExecFirewallExceptions(
1013 ExitOnFailure(hr, "failed to read protocol from custom action data"); 1029 ExitOnFailure(hr, "failed to read protocol from custom action data");
1014 hr = WcaReadStringFromCaData(&pwz, &pwzDescription); 1030 hr = WcaReadStringFromCaData(&pwz, &pwzDescription);
1015 ExitOnFailure(hr, "failed to read protocol from custom action data"); 1031 ExitOnFailure(hr, "failed to read protocol from custom action data");
1032 hr = WcaReadIntegerFromCaData(&pwz, &iDirection);
1033 ExitOnFailure(hr, "failed to read direction from custom action data");
1016 1034
1017 switch (iTarget) 1035 switch (iTarget)
1018 { 1036 {
@@ -1022,7 +1040,7 @@ extern "C" UINT __stdcall ExecFirewallExceptions(
1022 case WCA_TODO_INSTALL: 1040 case WCA_TODO_INSTALL:
1023 case WCA_TODO_REINSTALL: 1041 case WCA_TODO_REINSTALL:
1024 WcaLog(LOGMSG_STANDARD, "Installing firewall exception2 %ls on port %ls, protocol %d", pwzName, pwzPort, iProtocol); 1042 WcaLog(LOGMSG_STANDARD, "Installing firewall exception2 %ls on port %ls, protocol %d", pwzName, pwzPort, iProtocol);
1025 hr = AddPortException(fSupportProfiles, pwzName, iProfile, pwzRemoteAddresses, fIgnoreFailures, pwzPort, iProtocol, pwzDescription); 1043 hr = AddPortException(fSupportProfiles, pwzName, iProfile, pwzRemoteAddresses, fIgnoreFailures, pwzPort, iProtocol, pwzDescription, iDirection);
1026 ExitOnFailure(hr, "failed to add/update port exception for name '%ls' on port %ls, protocol %d", pwzName, pwzPort, iProtocol); 1044 ExitOnFailure(hr, "failed to add/update port exception for name '%ls' on port %ls, protocol %d", pwzName, pwzPort, iProtocol);
1027 break; 1045 break;
1028 1046
@@ -1040,7 +1058,7 @@ extern "C" UINT __stdcall ExecFirewallExceptions(
1040 case WCA_TODO_INSTALL: 1058 case WCA_TODO_INSTALL:
1041 case WCA_TODO_REINSTALL: 1059 case WCA_TODO_REINSTALL:
1042 WcaLog(LOGMSG_STANDARD, "Installing firewall exception2 %ls (%ls)", pwzName, pwzFile); 1060 WcaLog(LOGMSG_STANDARD, "Installing firewall exception2 %ls (%ls)", pwzName, pwzFile);
1043 hr = AddApplicationException(fSupportProfiles, pwzFile, pwzName, iProfile, pwzRemoteAddresses, fIgnoreFailures, pwzPort, iProtocol, pwzDescription); 1061 hr = AddApplicationException(fSupportProfiles, pwzFile, pwzName, iProfile, pwzRemoteAddresses, fIgnoreFailures, pwzPort, iProtocol, pwzDescription, iDirection);
1044 ExitOnFailure(hr, "failed to add/update application exception for name '%ls', file '%ls'", pwzName, pwzFile); 1062 ExitOnFailure(hr, "failed to add/update application exception for name '%ls', file '%ls'", pwzName, pwzFile);
1045 break; 1063 break;
1046 1064
diff --git a/src/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs b/src/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs
index 8f8ba44a..ceac4f26 100644
--- a/src/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs
+++ b/src/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs
@@ -25,7 +25,7 @@ namespace WixToolsetTest.Firewall
25 "CustomAction:Wix4RollbackFirewallExceptionsUninstall_X86\t3329\tWix4FWCA_X86\tExecFirewallExceptions\t", 25 "CustomAction:Wix4RollbackFirewallExceptionsUninstall_X86\t3329\tWix4FWCA_X86\tExecFirewallExceptions\t",
26 "CustomAction:Wix4SchedFirewallExceptionsInstall_X86\t1\tWix4FWCA_X86\tSchedFirewallExceptionsInstall\t", 26 "CustomAction:Wix4SchedFirewallExceptionsInstall_X86\t1\tWix4FWCA_X86\tSchedFirewallExceptionsInstall\t",
27 "CustomAction:Wix4SchedFirewallExceptionsUninstall_X86\t1\tWix4FWCA_X86\tSchedFirewallExceptionsUninstall\t", 27 "CustomAction:Wix4SchedFirewallExceptionsUninstall_X86\t1\tWix4FWCA_X86\tSchedFirewallExceptionsUninstall\t",
28 "WixFirewallException:ExampleFirewall\texample\t*\t42\t6\t\t0\t2147483647\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\tAn example firewall", 28 "WixFirewallException:ExampleFirewall\texample\t*\t42\t6\t\t0\t2147483647\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\tAn example firewall\t1",
29 }, results); 29 }, results);
30 } 30 }
31 31
@@ -44,7 +44,20 @@ namespace WixToolsetTest.Firewall
44 "CustomAction:Wix4RollbackFirewallExceptionsUninstall_A64\t3329\tWix4FWCA_A64\tExecFirewallExceptions\t", 44 "CustomAction:Wix4RollbackFirewallExceptionsUninstall_A64\t3329\tWix4FWCA_A64\tExecFirewallExceptions\t",
45 "CustomAction:Wix4SchedFirewallExceptionsInstall_A64\t1\tWix4FWCA_A64\tSchedFirewallExceptionsInstall\t", 45 "CustomAction:Wix4SchedFirewallExceptionsInstall_A64\t1\tWix4FWCA_A64\tSchedFirewallExceptionsInstall\t",
46 "CustomAction:Wix4SchedFirewallExceptionsUninstall_A64\t1\tWix4FWCA_A64\tSchedFirewallExceptionsUninstall\t", 46 "CustomAction:Wix4SchedFirewallExceptionsUninstall_A64\t1\tWix4FWCA_A64\tSchedFirewallExceptionsUninstall\t",
47 "WixFirewallException:ExampleFirewall\texample\t*\t42\t6\t\t0\t2147483647\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\tAn example firewall", 47 "WixFirewallException:ExampleFirewall\texample\t*\t42\t6\t\t0\t2147483647\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\tAn example firewall\t1",
48 }, results);
49 }
50
51 [Fact]
52 public void CanBuildUsingOutboundFirewall()
53 {
54 var folder = TestData.Get(@"TestData\UsingOutboundFirewall");
55 var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder });
56
57 var results = build.BuildAndQuery(Build, "WixFirewallException");
58 Assert.Equal(new[]
59 {
60 "WixFirewallException:fexPv9RR1kBvP6gMgWyXMVQkVbopOA\texample\t*\t42\t6\t\t0\t2147483647\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\tAn example outbound firewall\t2",
48 }, results); 61 }, results);
49 } 62 }
50 63
diff --git a/src/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/Package.en-us.wxl b/src/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/Package.en-us.wxl
new file mode 100644
index 00000000..38c12ac1
--- /dev/null
+++ b/src/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/Package.en-us.wxl
@@ -0,0 +1,11 @@
1<?xml version="1.0" encoding="utf-8"?>
2
3<!--
4This file contains the declaration of all the localizable strings.
5-->
6<WixLocalization xmlns="http://wixtoolset.org/schemas/v4/wxl" Culture="en-US">
7
8 <String Id="DowngradeError">A newer version of [ProductName] is already installed.</String>
9 <String Id="FeatureTitle">MsiPackage</String>
10
11</WixLocalization>
diff --git a/src/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/Package.wxs b/src/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/Package.wxs
new file mode 100644
index 00000000..68ff98fd
--- /dev/null
+++ b/src/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/Package.wxs
@@ -0,0 +1,22 @@
1<?xml version="1.0" encoding="utf-8"?>
2<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
3 <Product Id="*" Name="MsiPackage" Language="1033" Version="1.0.0.0" Manufacturer="Example Corporation" UpgradeCode="047730a5-30fe-4a62-a520-da9381b8226a">
4 <Package InstallerVersion="200" Compressed="no" InstallScope="perMachine" />
5
6 <MajorUpgrade DowngradeErrorMessage="!(loc.DowngradeError)" />
7 <MediaTemplate />
8
9 <Feature Id="ProductFeature" Title="!(loc.FeatureTitle)">
10 <ComponentGroupRef Id="ProductComponents" />
11 </Feature>
12
13 </Product>
14
15 <Fragment>
16 <Directory Id="TARGETDIR" Name="SourceDir">
17 <Directory Id="ProgramFilesFolder">
18 <Directory Id="INSTALLFOLDER" Name="MsiPackage" />
19 </Directory>
20 </Directory>
21 </Fragment>
22</Wix>
diff --git a/src/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/PackageComponents.wxs b/src/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/PackageComponents.wxs
new file mode 100644
index 00000000..f8c1e781
--- /dev/null
+++ b/src/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/PackageComponents.wxs
@@ -0,0 +1,14 @@
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>
7 <File Source="example.txt" />
8 <fw:FirewallException Description="An example outbound firewall" Name="example" Port="42" Outbound="yes">
9 <fw:RemoteAddress>*</fw:RemoteAddress>
10 </fw:FirewallException>
11 </Component>
12 </ComponentGroup>
13 </Fragment>
14</Wix>
diff --git a/src/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/example.txt b/src/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/example.txt
new file mode 100644
index 00000000..1b4ffe8a
--- /dev/null
+++ b/src/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/example.txt
@@ -0,0 +1 @@
This is example.txt. \ No newline at end of file
diff --git a/src/test/WixToolsetTest.Firewall/WixToolsetTest.Firewall.csproj b/src/test/WixToolsetTest.Firewall/WixToolsetTest.Firewall.csproj
index 7727a69b..d04368c1 100644
--- a/src/test/WixToolsetTest.Firewall/WixToolsetTest.Firewall.csproj
+++ b/src/test/WixToolsetTest.Firewall/WixToolsetTest.Firewall.csproj
@@ -16,6 +16,10 @@
16 <Content Include="TestData\UsingFirewall\Package.en-us.wxl" CopyToOutputDirectory="PreserveNewest" /> 16 <Content Include="TestData\UsingFirewall\Package.en-us.wxl" CopyToOutputDirectory="PreserveNewest" />
17 <Content Include="TestData\UsingFirewall\Package.wxs" CopyToOutputDirectory="PreserveNewest" /> 17 <Content Include="TestData\UsingFirewall\Package.wxs" CopyToOutputDirectory="PreserveNewest" />
18 <Content Include="TestData\UsingFirewall\PackageComponents.wxs" CopyToOutputDirectory="PreserveNewest" /> 18 <Content Include="TestData\UsingFirewall\PackageComponents.wxs" CopyToOutputDirectory="PreserveNewest" />
19 <Content Include="TestData\UsingOutboundFirewall\example.txt" CopyToOutputDirectory="PreserveNewest" />
20 <Content Include="TestData\UsingOutboundFirewall\Package.en-us.wxl" CopyToOutputDirectory="PreserveNewest" />
21 <Content Include="TestData\UsingOutboundFirewall\Package.wxs" CopyToOutputDirectory="PreserveNewest" />
22 <Content Include="TestData\UsingOutboundFirewall\PackageComponents.wxs" CopyToOutputDirectory="PreserveNewest" />
19 </ItemGroup> 23 </ItemGroup>
20 24
21 <ItemGroup> 25 <ItemGroup>
diff --git a/src/wixext/FirewallCompiler.cs b/src/wixext/FirewallCompiler.cs
index 1fa80f48..900af7aa 100644
--- a/src/wixext/FirewallCompiler.cs
+++ b/src/wixext/FirewallCompiler.cs
@@ -81,6 +81,7 @@ namespace WixToolset.Firewall
81 string scope = null; 81 string scope = null;
82 string remoteAddresses = null; 82 string remoteAddresses = null;
83 string description = null; 83 string description = null;
84 int? direction = null;
84 85
85 foreach (var attrib in element.Attributes()) 86 foreach (var attrib in element.Attributes())
86 { 87 {
@@ -177,6 +178,11 @@ namespace WixToolset.Firewall
177 case "Description": 178 case "Description":
178 description = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); 179 description = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
179 break; 180 break;
181 case "Outbound":
182 direction = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib) == YesNoType.Yes
183 ? FirewallConstants.NET_FW_RULE_DIR_OUT
184 : FirewallConstants.NET_FW_RULE_DIR_IN;
185 break;
180 default: 186 default:
181 this.ParseHelper.UnexpectedAttribute(element, attrib); 187 this.ParseHelper.UnexpectedAttribute(element, attrib);
182 break; 188 break;
@@ -260,6 +266,7 @@ namespace WixToolset.Firewall
260 Profile = profile ?? FirewallConstants.NET_FW_PROFILE2_ALL, 266 Profile = profile ?? FirewallConstants.NET_FW_PROFILE2_ALL,
261 ComponentRef = componentId, 267 ComponentRef = componentId,
262 Description = description, 268 Description = description,
269 Direction = direction ?? FirewallConstants.NET_FW_RULE_DIR_IN,
263 }); 270 });
264 271
265 if (!String.IsNullOrEmpty(port)) 272 if (!String.IsNullOrEmpty(port))
diff --git a/src/wixext/FirewallConstants.cs b/src/wixext/FirewallConstants.cs
index 16caa5b4..7bb12ba4 100644
--- a/src/wixext/FirewallConstants.cs
+++ b/src/wixext/FirewallConstants.cs
@@ -9,6 +9,8 @@ namespace WixToolset.Firewall
9 static class FirewallConstants 9 static class FirewallConstants
10 { 10 {
11 // from icftypes.h 11 // from icftypes.h
12 public const int NET_FW_RULE_DIR_IN = 1;
13 public const int NET_FW_RULE_DIR_OUT = 2;
12 public const int NET_FW_IP_PROTOCOL_TCP = 6; 14 public const int NET_FW_IP_PROTOCOL_TCP = 6;
13 public const int NET_FW_IP_PROTOCOL_UDP = 17; 15 public const int NET_FW_IP_PROTOCOL_UDP = 17;
14 16
diff --git a/src/wixext/FirewallDecompiler.cs b/src/wixext/FirewallDecompiler.cs
index b060f8e2..c9478de1 100644
--- a/src/wixext/FirewallDecompiler.cs
+++ b/src/wixext/FirewallDecompiler.cs
@@ -146,6 +146,19 @@ namespace WixToolset.Firewall
146 fire.Description = (string)row[9]; 146 fire.Description = (string)row[9];
147 } 147 }
148 148
149 if (!row.IsColumnEmpty(10))
150 {
151 switch (Convert.ToInt32(row[10]))
152 {
153 case FirewallConstants.NET_FW_RULE_DIR_IN:
154 fire.Direction = Firewall.FirewallException.DirectionType.@in;
155 break;
156 case FirewallConstants.NET_FW_RULE_DIR_OUT:
157 fire.Direction = Firewall.FirewallException.DirectionType.@out;
158 break;
159 }
160 }
161
149 Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[8]); 162 Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[8]);
150 if (null != component) 163 if (null != component)
151 { 164 {
diff --git a/src/wixext/FirewallTableDefinitions.cs b/src/wixext/FirewallTableDefinitions.cs
index 4bae1ef0..068fe696 100644
--- a/src/wixext/FirewallTableDefinitions.cs
+++ b/src/wixext/FirewallTableDefinitions.cs
@@ -21,6 +21,7 @@ namespace WixToolset.Firewall
21 new ColumnDefinition("Profile", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Integer, minValue: 1, maxValue: 2147483647, description: "Profile (1=domain; 2=private; 4=public; 2147483647=all)."), 21 new ColumnDefinition("Profile", ColumnType.Number, 4, primaryKey: false, nullable: false, ColumnCategory.Integer, minValue: 1, maxValue: 2147483647, description: "Profile (1=domain; 2=private; 4=public; 2147483647=all)."),
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 }, 25 },
25 tupleIdIsPrimaryKey: true 26 tupleIdIsPrimaryKey: true
26 ); 27 );
diff --git a/src/wixext/Tuples/WixFirewallExceptionTuple.cs b/src/wixext/Tuples/WixFirewallExceptionTuple.cs
index d08b9e45..d34b8207 100644
--- a/src/wixext/Tuples/WixFirewallExceptionTuple.cs
+++ b/src/wixext/Tuples/WixFirewallExceptionTuple.cs
@@ -20,6 +20,7 @@ namespace WixToolset.Firewall
20 new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Profile), IntermediateFieldType.Number), 20 new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Profile), IntermediateFieldType.Number),
21 new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.ComponentRef), IntermediateFieldType.String), 21 new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.ComponentRef), IntermediateFieldType.String),
22 new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Description), IntermediateFieldType.String), 22 new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Description), IntermediateFieldType.String),
23 new IntermediateFieldDefinition(nameof(WixFirewallExceptionTupleFields.Direction), IntermediateFieldType.Number),
23 }, 24 },
24 typeof(WixFirewallExceptionTuple)); 25 typeof(WixFirewallExceptionTuple));
25 } 26 }
@@ -40,6 +41,7 @@ namespace WixToolset.Firewall.Tuples
40 Profile, 41 Profile,
41 ComponentRef, 42 ComponentRef,
42 Description, 43 Description,
44 Direction,
43 } 45 }
44 46
45 public class WixFirewallExceptionTuple : IntermediateTuple 47 public class WixFirewallExceptionTuple : IntermediateTuple
@@ -107,5 +109,11 @@ namespace WixToolset.Firewall.Tuples
107 get => this.Fields[(int)WixFirewallExceptionTupleFields.Description].AsString(); 109 get => this.Fields[(int)WixFirewallExceptionTupleFields.Description].AsString();
108 set => this.Set((int)WixFirewallExceptionTupleFields.Description, value); 110 set => this.Set((int)WixFirewallExceptionTupleFields.Description, value);
109 } 111 }
112
113 public int Direction
114 {
115 get => this.Fields[(int)WixFirewallExceptionTupleFields.Direction].AsNumber();
116 set => this.Set((int)WixFirewallExceptionTupleFields.Direction, value);
117 }
110 } 118 }
111} \ No newline at end of file 119} \ No newline at end of file
diff --git a/src/wixext/firewall.xsd b/src/wixext/firewall.xsd
index d64aafef..fec7e37a 100644
--- a/src/wixext/firewall.xsd
+++ b/src/wixext/firewall.xsd
@@ -141,7 +141,7 @@
141 <xs:attribute name="IgnoreFailure" type="YesNoType"> 141 <xs:attribute name="IgnoreFailure" type="YesNoType">
142 <xs:annotation> 142 <xs:annotation>
143 <xs:documentation> 143 <xs:documentation>
144 If "yes," failures to register this firewall exception will be silently 144 If "yes", failures to register this firewall exception will be silently
145 ignored. If "no" (the default), failures will cause rollback. 145 ignored. If "no" (the default), failures will cause rollback.
146 </xs:documentation> 146 </xs:documentation>
147 </xs:annotation> 147 </xs:annotation>
@@ -170,6 +170,14 @@
170 </xs:documentation> 170 </xs:documentation>
171 </xs:annotation> 171 </xs:annotation>
172 </xs:attribute> 172 </xs:attribute>
173
174 <xs:attribute name="Outbound" type="YesNoType">
175 <xs:annotation>
176 <xs:documentation>
177 If "yes", registers an outbound firewall rule.
178 </xs:documentation>
179 </xs:annotation>
180 </xs:attribute>
173 </xs:complexType> 181 </xs:complexType>
174 </xs:element> 182 </xs:element>
175 183
diff --git a/src/wixlib/firewall.wixproj b/src/wixlib/firewall.wixproj
index cb273a38..c1daa05a 100644
--- a/src/wixlib/firewall.wixproj
+++ b/src/wixlib/firewall.wixproj
@@ -1,7 +1,7 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. --> 2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3<Project DefaultTargets="Build" InitialTargets="EnsureWixToolsetInstalled" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="15.0"> 3<Project DefaultTargets="Build" InitialTargets="EnsureWixToolsetInstalled" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="15.0">
4 <Import Project="..\..\packages\WixToolset.MSBuild.4.0.0-build-0093\build\WixToolset.MSBuild.props" Condition="Exists('..\..\packages\WixToolset.MSBuild.4.0.0-build-0093\build\WixToolset.MSBuild.props')" /> 4 <Import Project="..\..\packages\WixToolset.MSBuild.4.0.0-build-0102\build\WixToolset.MSBuild.props" Condition="Exists('..\..\packages\WixToolset.MSBuild.4.0.0-build-0102\build\WixToolset.MSBuild.props')" />
5 <Import Project="..\FindLocalWix.props" /> 5 <Import Project="..\FindLocalWix.props" />
6 <PropertyGroup> 6 <PropertyGroup>
7 <ProjectGuid>{1acffefd-505a-41a5-acbf-a02b7b473aa2}</ProjectGuid> 7 <ProjectGuid>{1acffefd-505a-41a5-acbf-a02b7b473aa2}</ProjectGuid>
@@ -73,7 +73,7 @@
73 <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> 73 <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
74 </PropertyGroup> 74 </PropertyGroup>
75 <Error Condition="!Exists('..\..\packages\Nerdbank.GitVersioning.2.1.65\build\Nerdbank.GitVersioning.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Nerdbank.GitVersioning.2.1.65\build\Nerdbank.GitVersioning.targets'))" /> 75 <Error Condition="!Exists('..\..\packages\Nerdbank.GitVersioning.2.1.65\build\Nerdbank.GitVersioning.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\Nerdbank.GitVersioning.2.1.65\build\Nerdbank.GitVersioning.targets'))" />
76 <Error Condition="!Exists('..\..\packages\WixToolset.MSBuild.4.0.0-build-0093\build\WixToolset.MSBuild.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\WixToolset.MSBuild.4.0.0-build-0093\build\WixToolset.MSBuild.props'))" /> 76 <Error Condition="!Exists('..\..\packages\WixToolset.MSBuild.4.0.0-build-0102\build\WixToolset.MSBuild.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\WixToolset.MSBuild.4.0.0-build-0102\build\WixToolset.MSBuild.props'))" />
77 </Target> 77 </Target>
78 <Import Project="..\..\packages\Nerdbank.GitVersioning.2.1.65\build\Nerdbank.GitVersioning.targets" Condition="Exists('..\..\packages\Nerdbank.GitVersioning.2.1.65\build\Nerdbank.GitVersioning.targets')" /> 78 <Import Project="..\..\packages\Nerdbank.GitVersioning.2.1.65\build\Nerdbank.GitVersioning.targets" Condition="Exists('..\..\packages\Nerdbank.GitVersioning.2.1.65\build\Nerdbank.GitVersioning.targets')" />
79</Project> \ No newline at end of file 79</Project> \ No newline at end of file
diff --git a/src/wixlib/packages.config b/src/wixlib/packages.config
index 20afb58c..8db41667 100644
--- a/src/wixlib/packages.config
+++ b/src/wixlib/packages.config
@@ -1,5 +1,5 @@
1<?xml version="1.0" encoding="utf-8"?> 1<?xml version="1.0" encoding="utf-8"?>
2<packages> 2<packages>
3 <package id="Nerdbank.GitVersioning" version="2.1.65" developmentDependency="true" targetFramework="net40" /> 3 <package id="Nerdbank.GitVersioning" version="2.1.65" developmentDependency="true" targetFramework="net40" />
4 <package id="WixToolset.MSBuild" version="4.0.0-build-0093" developmentDependency="true" targetFramework="net40" /> 4 <package id="WixToolset.MSBuild" version="4.0.0-build-0102" developmentDependency="true" targetFramework="net40" />
5</packages> \ No newline at end of file 5</packages> \ No newline at end of file