aboutsummaryrefslogtreecommitdiff
path: root/src/ext/Firewall
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2021-05-04 22:46:07 -0700
committerRob Mensching <rob@firegiant.com>2021-05-04 22:46:07 -0700
commitba00d844a2e2716a6aa07df89dd9318608bd1909 (patch)
tree0738ebcbcea51a9e4736efbbc19c68d17202ecad /src/ext/Firewall
parentbfabd9f718af70e59f24ac70046fa3141daf06e8 (diff)
downloadwix-ba00d844a2e2716a6aa07df89dd9318608bd1909.tar.gz
wix-ba00d844a2e2716a6aa07df89dd9318608bd1909.tar.bz2
wix-ba00d844a2e2716a6aa07df89dd9318608bd1909.zip
Move Firewall.wixext into ext
Diffstat (limited to 'src/ext/Firewall')
-rw-r--r--src/ext/Firewall/CSharp.Build.props11
-rw-r--r--src/ext/Firewall/Cpp.Build.props86
-rw-r--r--src/ext/Firewall/Directory.Build.props29
-rw-r--r--src/ext/Firewall/Directory.Build.targets48
-rw-r--r--src/ext/Firewall/Firewall.wixext.sln73
-rw-r--r--src/ext/Firewall/Firewall.wixext.v3.ncrunchsolution6
-rw-r--r--src/ext/Firewall/README.md2
-rw-r--r--src/ext/Firewall/appveyor.cmd14
-rw-r--r--src/ext/Firewall/appveyor.yml40
-rw-r--r--src/ext/Firewall/ca/CustomMsiErrors.h130
-rw-r--r--src/ext/Firewall/ca/caDecor.h13
-rw-r--r--src/ext/Firewall/ca/cost.h5
-rw-r--r--src/ext/Firewall/ca/dllmain.cpp26
-rw-r--r--src/ext/Firewall/ca/firewall.cpp1085
-rw-r--r--src/ext/Firewall/ca/fwca.def9
-rw-r--r--src/ext/Firewall/ca/fwca.v3.ncrunchproject5
-rw-r--r--src/ext/Firewall/ca/fwca.vcxproj81
-rw-r--r--src/ext/Firewall/ca/packages.config5
-rw-r--r--src/ext/Firewall/ca/precomp.h19
-rw-r--r--src/ext/Firewall/nuget.config18
-rw-r--r--src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs80
-rw-r--r--src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/Package.en-us.wxl11
-rw-r--r--src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/Package.wxs15
-rw-r--r--src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/PackageComponents.wxs14
-rw-r--r--src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/example.txt1
-rw-r--r--src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/Package.en-us.wxl11
-rw-r--r--src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/Package.wxs15
-rw-r--r--src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/PackageComponents.wxs14
-rw-r--r--src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/example.txt1
-rw-r--r--src/ext/Firewall/test/WixToolsetTest.Firewall/WixToolsetTest.Firewall.csproj45
-rw-r--r--src/ext/Firewall/test/WixToolsetTest.Firewall/WixToolsetTest.Firewall.v3.ncrunchproject5
-rw-r--r--src/ext/Firewall/wix.snkbin0 -> 596 bytes
-rw-r--r--src/ext/Firewall/wixext/FirewallCompiler.cs354
-rw-r--r--src/ext/Firewall/wixext/FirewallConstants.cs23
-rw-r--r--src/ext/Firewall/wixext/FirewallDecompiler.cs182
-rw-r--r--src/ext/Firewall/wixext/FirewallErrors.cs36
-rw-r--r--src/ext/Firewall/wixext/FirewallExtensionData.cs23
-rw-r--r--src/ext/Firewall/wixext/FirewallExtensionFactory.cs18
-rw-r--r--src/ext/Firewall/wixext/FirewallTableDefinitions.cs34
-rw-r--r--src/ext/Firewall/wixext/FirewallWindowsInstallerBackendExtension.cs13
-rw-r--r--src/ext/Firewall/wixext/Symbols/FirewallSymbolDefinitions.cs39
-rw-r--r--src/ext/Firewall/wixext/Symbols/WixFirewallExceptionSymbol.cs119
-rw-r--r--src/ext/Firewall/wixext/WixToolset.Firewall.wixext.csproj31
-rw-r--r--src/ext/Firewall/wixext/WixToolset.Firewall.wixext.targets11
-rw-r--r--src/ext/Firewall/wixlib/FirewallExtension.wxs11
-rw-r--r--src/ext/Firewall/wixlib/FirewallExtension_Platform.wxi36
-rw-r--r--src/ext/Firewall/wixlib/FirewallExtension_arm64.wxs7
-rw-r--r--src/ext/Firewall/wixlib/FirewallExtension_x64.wxs7
-rw-r--r--src/ext/Firewall/wixlib/FirewallExtension_x86.wxs7
-rw-r--r--src/ext/Firewall/wixlib/caDecor.wxi39
-rw-r--r--src/ext/Firewall/wixlib/caerr.wxi96
-rw-r--r--src/ext/Firewall/wixlib/en-us.wxl13
-rw-r--r--src/ext/Firewall/wixlib/es-es.wxl12
-rw-r--r--src/ext/Firewall/wixlib/firewall.v3.ncrunchproject5
-rw-r--r--src/ext/Firewall/wixlib/firewall.wixproj26
-rw-r--r--src/ext/Firewall/wixlib/ja-jp.wxl13
-rw-r--r--src/ext/Firewall/wixlib/pl-pl.wxl13
57 files changed, 3085 insertions, 0 deletions
diff --git a/src/ext/Firewall/CSharp.Build.props b/src/ext/Firewall/CSharp.Build.props
new file mode 100644
index 00000000..b12f4c6e
--- /dev/null
+++ b/src/ext/Firewall/CSharp.Build.props
@@ -0,0 +1,11 @@
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 Do NOT modify this file. Update the canonical version in Home\repo-template\src\CSharp.Build.props
4 then update all of the repos.
5-->
6<Project>
7 <PropertyGroup>
8 <SignAssembly>true</SignAssembly>
9 <AssemblyOriginatorKeyFile>$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)wix.snk))</AssemblyOriginatorKeyFile>
10 </PropertyGroup>
11</Project>
diff --git a/src/ext/Firewall/Cpp.Build.props b/src/ext/Firewall/Cpp.Build.props
new file mode 100644
index 00000000..9b7a1bb5
--- /dev/null
+++ b/src/ext/Firewall/Cpp.Build.props
@@ -0,0 +1,86 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4<Project>
5 <PropertyGroup>
6 <Platform Condition=" '$(Platform)' == '' OR '$(Platform)' == 'AnyCPU' ">Win32</Platform>
7 <IntDir>$(BaseIntermediateOutputPath)$(Configuration)\$(Platform)\</IntDir>
8 <OutDir>$(OutputPath)$(Platform)\</OutDir>
9 </PropertyGroup>
10
11 <PropertyGroup Condition="'$(WindowsTargetPlatformVersion)'=='' AND '$(VisualStudioVersion)'>='15.0'">
12 <WindowsTargetPlatformVersion>$([Microsoft.Build.Utilities.ToolLocationHelper]::GetLatestSDKTargetPlatformVersion('Windows', '10.0'))</WindowsTargetPlatformVersion>
13 </PropertyGroup>
14
15 <ItemDefinitionGroup>
16 <ClCompile>
17 <DisableSpecificWarnings>$(DisableSpecificCompilerWarnings)</DisableSpecificWarnings>
18 <WarningLevel>Level4</WarningLevel>
19 <AdditionalIncludeDirectories>$(ProjectDir)inc;$(MSBuildProjectDirectory);$(IntDir);$(SqlCESdkIncludePath);$(ProjectAdditionalIncludeDirectories);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
20 <PreprocessorDefinitions>WIN32;_WINDOWS;_WIN32_MSI=500;_WIN32_WINNT=0x0501;$(ArmPreprocessorDefinitions);$(UnicodePreprocessorDefinitions);_CRT_STDIO_LEGACY_WIDE_SPECIFIERS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
21 <PrecompiledHeader>Use</PrecompiledHeader>
22 <PrecompiledHeaderFile>precomp.h</PrecompiledHeaderFile>
23 <CallingConvention Condition="'$(Platform)'=='Win32'">StdCall</CallingConvention>
24 <TreatWarningAsError>true</TreatWarningAsError>
25 <ExceptionHandling>false</ExceptionHandling>
26 <AdditionalOptions>-YlprecompDefine</AdditionalOptions>
27 <AdditionalOptions Condition=" $(PlatformToolset.StartsWith('v14')) ">/Zc:threadSafeInit- %(AdditionalOptions)</AdditionalOptions>
28 <MultiProcessorCompilation Condition=" $(NUMBER_OF_PROCESSORS) &gt; 4 ">true</MultiProcessorCompilation>
29 </ClCompile>
30 <ResourceCompile>
31 <PreprocessorDefinitions>$(ArmPreprocessorDefinitions);%(PreprocessorDefinitions)</PreprocessorDefinitions>
32 <AdditionalIncludeDirectories>$(ProjectAdditionalResourceIncludeDirectories);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
33 </ResourceCompile>
34 <Lib>
35 <AdditionalLibraryDirectories>$(OutDir);$(AdditionalMultiTargetLibraryPath);$(ProjectAdditionalLibraryDirectories);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
36 </Lib>
37 <Link>
38 <SubSystem>$(ProjectSubSystem)</SubSystem>
39 <ModuleDefinitionFile>$(ProjectModuleDefinitionFile)</ModuleDefinitionFile>
40 <NoEntryPoint>$(ResourceOnlyDll)</NoEntryPoint>
41 <GenerateDebugInformation>true</GenerateDebugInformation>
42 <AdditionalDependencies>$(ProjectAdditionalLinkLibraries);advapi32.lib;comdlg32.lib;user32.lib;oleaut32.lib;gdi32.lib;shell32.lib;ole32.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
43 <AdditionalLibraryDirectories>$(OutDir);$(AdditionalMultiTargetLibraryPath);$(ArmLibraryDirectories);$(ProjectAdditionalLinkLibraryDirectories);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
44 <AdditionalOptions Condition=" $(PlatformToolset.StartsWith('v14')) ">/IGNORE:4099 %(AdditionalOptions)</AdditionalOptions>
45 </Link>
46 </ItemDefinitionGroup>
47
48 <ItemDefinitionGroup Condition=" '$(Platform)'=='Win32' and '$(PlatformToolset)'!='v100'">
49 <ClCompile>
50 <EnableEnhancedInstructionSet>NoExtensions</EnableEnhancedInstructionSet>
51 </ClCompile>
52 </ItemDefinitionGroup>
53 <ItemDefinitionGroup Condition=" '$(Platform)'=='arm' ">
54 <ClCompile>
55 <CallingConvention>CDecl</CallingConvention>
56 </ClCompile>
57 </ItemDefinitionGroup>
58 <ItemDefinitionGroup Condition=" '$(ConfigurationType)'=='StaticLibrary' ">
59 <ClCompile>
60 <DebugInformationFormat>OldStyle</DebugInformationFormat>
61 <OmitDefaultLibName>true</OmitDefaultLibName>
62 <IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
63 </ClCompile>
64 </ItemDefinitionGroup>
65 <ItemDefinitionGroup Condition=" '$(Configuration)'=='Debug' ">
66 <ClCompile>
67 <Optimization>Disabled</Optimization>
68 <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
69 <PreprocessorDefinitions>_DEBUG;DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
70 <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
71 </ClCompile>
72 </ItemDefinitionGroup>
73 <ItemDefinitionGroup Condition=" '$(Configuration)'=='Release' ">
74 <ClCompile>
75 <Optimization>MinSpace</Optimization>
76 <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
77 <FunctionLevelLinking>true</FunctionLevelLinking>
78 <IntrinsicFunctions>true</IntrinsicFunctions>
79 <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
80 </ClCompile>
81 <Link>
82 <EnableCOMDATFolding>true</EnableCOMDATFolding>
83 <OptimizeReferences>true</OptimizeReferences>
84 </Link>
85 </ItemDefinitionGroup>
86</Project>
diff --git a/src/ext/Firewall/Directory.Build.props b/src/ext/Firewall/Directory.Build.props
new file mode 100644
index 00000000..f83cc154
--- /dev/null
+++ b/src/ext/Firewall/Directory.Build.props
@@ -0,0 +1,29 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3<!--
4 Do NOT modify this file. Update the canonical version in Home\repo-template\src\Directory.Build.props
5 then update all of the repos.
6-->
7<Project>
8 <PropertyGroup>
9 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
10 <EnableSourceLink Condition=" '$(NCrunch)' == '1' ">false</EnableSourceLink>
11 <MSBuildWarningsAsMessages>MSB3246</MSBuildWarningsAsMessages>
12
13 <ProjectName Condition=" '$(ProjectName)' == '' ">$(MSBuildProjectName)</ProjectName>
14 <BaseOutputPath>$([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)..\build\))</BaseOutputPath>
15 <BaseIntermediateOutputPath>$(BaseOutputPath)obj\$(ProjectName)\</BaseIntermediateOutputPath>
16 <OutputPath>$(BaseOutputPath)$(Configuration)\</OutputPath>
17
18 <Authors>WiX Toolset Team</Authors>
19 <Company>WiX Toolset</Company>
20 <Copyright>Copyright (c) .NET Foundation and contributors. All rights reserved.</Copyright>
21 <PackageLicenseExpression>MS-RL</PackageLicenseExpression>
22 <Product>WiX Toolset</Product>
23 </PropertyGroup>
24
25 <Import Project="CSharp.Build.props" Condition=" '$(MSBuildProjectExtension)'=='.csproj' and Exists('CSharp.Build.props') " />
26 <Import Project="Cpp.Build.props" Condition=" Exists('Cpp.Build.props') And '$(MSBuildProjectExtension)'=='.vcxproj' " />
27 <Import Project="Wix.Build.props" Condition=" Exists('Wix.Build.props') And '$(MSBuildProjectExtension)'=='.wixproj' " />
28 <Import Project="Custom.Build.props" Condition=" Exists('Custom.Build.props') " />
29</Project>
diff --git a/src/ext/Firewall/Directory.Build.targets b/src/ext/Firewall/Directory.Build.targets
new file mode 100644
index 00000000..dac7452a
--- /dev/null
+++ b/src/ext/Firewall/Directory.Build.targets
@@ -0,0 +1,48 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3<!--
4 Do NOT modify this file. Update the canonical version in Home\repo-template\src\Directory.Build.targets
5 then update all of the repos.
6-->
7<!--
8 Replace PackageReferences with ProjectReferences when the projects can be found in .sln.
9 See the original here: https://github.com/dotnet/sdk/issues/1151#issuecomment-385133284
10-->
11<Project>
12 <PropertyGroup>
13 <ReplacePackageReferences>true</ReplacePackageReferences>
14 <TheSolutionPath Condition=" '$(NCrunch)'=='' ">$(SolutionPath)</TheSolutionPath>
15 <TheSolutionPath Condition=" '$(NCrunch)'=='1' ">$(NCrunchOriginalSolutionPath)</TheSolutionPath>
16 </PropertyGroup>
17
18 <Choose>
19 <When Condition="$(ReplacePackageReferences) AND '$(TheSolutionPath)' != '' AND '$(TheSolutionPath)' != '*undefined*' AND Exists('$(TheSolutionPath)')">
20
21 <PropertyGroup>
22 <SolutionFileContent>$([System.IO.File]::ReadAllText($(TheSolutionPath)))</SolutionFileContent>
23 <SmartSolutionDir>$([System.IO.Path]::GetDirectoryName( $(TheSolutionPath) ))</SmartSolutionDir>
24 <RegexPattern>(?&lt;="[PackageName]", ")(.*)(?=", ")</RegexPattern>
25 </PropertyGroup>
26
27 <ItemGroup>
28 <!-- Keep the identity of the PackageReference -->
29 <SmartPackageReference Include="@(PackageReference)">
30 <PackageName>%(Identity)</PackageName>
31 <InSolution>$(SolutionFileContent.Contains('\%(Identity).csproj'))</InSolution>
32 </SmartPackageReference>
33
34 <!-- Filter them by mapping them to another ItemGroup using the WithMetadataValue item function -->
35 <PackageInSolution Include="@(SmartPackageReference->WithMetadataValue('InSolution', True))">
36 <Pattern>$(RegexPattern.Replace('[PackageName]','%(PackageName)') )</Pattern>
37 <SmartPath>$([System.Text.RegularExpressions.Regex]::Match('$(SolutionFileContent)', '%(Pattern)'))</SmartPath>
38 </PackageInSolution>
39
40 <ProjectReference Include="@(PackageInSolution->'$(SmartSolutionDir)\%(SmartPath)' )"/>
41
42 <!-- Remove the package references that are now referenced as projects -->
43 <PackageReference Remove="@(PackageInSolution->'%(PackageName)' )"/>
44 </ItemGroup>
45
46 </When>
47 </Choose>
48</Project>
diff --git a/src/ext/Firewall/Firewall.wixext.sln b/src/ext/Firewall/Firewall.wixext.sln
new file mode 100644
index 00000000..59209c88
--- /dev/null
+++ b/src/ext/Firewall/Firewall.wixext.sln
@@ -0,0 +1,73 @@
1
2Microsoft Visual Studio Solution File, Format Version 12.00
3# Visual Studio 15
4VisualStudioVersion = 15.0.27130.2003
5MinimumVisualStudioVersion = 15.0.26124.0
6Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fwca", "src\ca\fwca.vcxproj", "{F72D34CA-48DA-4DFD-91A9-A0C78BEF6981}"
7EndProject
8Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "firewall", "src\wixlib\firewall.wixproj", "{1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}"
9EndProject
10Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.Firewall.wixext", "src\wixext\WixToolset.Firewall.wixext.csproj", "{6CF033EB-0A39-4AC6-9D41-9BD506352045}"
11EndProject
12Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolsetTest.Firewall", "src\test\WixToolsetTest.Firewall\WixToolsetTest.Firewall.csproj", "{D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}"
13EndProject
14Global
15 GlobalSection(SolutionConfigurationPlatforms) = preSolution
16 Debug|Any CPU = Debug|Any CPU
17 Debug|x64 = Debug|x64
18 Debug|x86 = Debug|x86
19 Release|Any CPU = Release|Any CPU
20 Release|x64 = Release|x64
21 Release|x86 = Release|x86
22 EndGlobalSection
23 GlobalSection(ProjectConfigurationPlatforms) = postSolution
24 {F72D34CA-48DA-4DFD-91A9-A0C78BEF6981}.Debug|Any CPU.ActiveCfg = Debug|Win32
25 {F72D34CA-48DA-4DFD-91A9-A0C78BEF6981}.Debug|Any CPU.Build.0 = Debug|Win32
26 {F72D34CA-48DA-4DFD-91A9-A0C78BEF6981}.Debug|x64.ActiveCfg = Debug|Win32
27 {F72D34CA-48DA-4DFD-91A9-A0C78BEF6981}.Debug|x86.ActiveCfg = Debug|Win32
28 {F72D34CA-48DA-4DFD-91A9-A0C78BEF6981}.Debug|x86.Build.0 = Debug|Win32
29 {F72D34CA-48DA-4DFD-91A9-A0C78BEF6981}.Release|Any CPU.ActiveCfg = Release|Win32
30 {F72D34CA-48DA-4DFD-91A9-A0C78BEF6981}.Release|x64.ActiveCfg = Release|Win32
31 {F72D34CA-48DA-4DFD-91A9-A0C78BEF6981}.Release|x86.ActiveCfg = Release|Win32
32 {F72D34CA-48DA-4DFD-91A9-A0C78BEF6981}.Release|x86.Build.0 = Release|Win32
33 {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Debug|Any CPU.ActiveCfg = Debug|x86
34 {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Debug|Any CPU.Build.0 = Debug|x86
35 {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Debug|x64.ActiveCfg = Debug|x86
36 {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Debug|x86.ActiveCfg = Debug|x86
37 {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Debug|x86.Build.0 = Debug|x86
38 {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Release|Any CPU.ActiveCfg = Release|x86
39 {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Release|x64.ActiveCfg = Release|x86
40 {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Release|x86.ActiveCfg = Release|x86
41 {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Release|x86.Build.0 = Release|x86
42 {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
43 {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Debug|Any CPU.Build.0 = Debug|Any CPU
44 {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Debug|x64.ActiveCfg = Debug|Any CPU
45 {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Debug|x64.Build.0 = Debug|Any CPU
46 {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Debug|x86.ActiveCfg = Debug|Any CPU
47 {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Debug|x86.Build.0 = Debug|Any CPU
48 {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Release|Any CPU.ActiveCfg = Release|Any CPU
49 {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Release|Any CPU.Build.0 = Release|Any CPU
50 {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Release|x64.ActiveCfg = Release|Any CPU
51 {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Release|x64.Build.0 = Release|Any CPU
52 {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Release|x86.ActiveCfg = Release|Any CPU
53 {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Release|x86.Build.0 = Release|Any CPU
54 {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
55 {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Debug|Any CPU.Build.0 = Debug|Any CPU
56 {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Debug|x64.ActiveCfg = Debug|Any CPU
57 {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Debug|x64.Build.0 = Debug|Any CPU
58 {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Debug|x86.ActiveCfg = Debug|Any CPU
59 {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Debug|x86.Build.0 = Debug|Any CPU
60 {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Release|Any CPU.ActiveCfg = Release|Any CPU
61 {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Release|Any CPU.Build.0 = Release|Any CPU
62 {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Release|x64.ActiveCfg = Release|Any CPU
63 {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Release|x64.Build.0 = Release|Any CPU
64 {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Release|x86.ActiveCfg = Release|Any CPU
65 {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Release|x86.Build.0 = Release|Any CPU
66 EndGlobalSection
67 GlobalSection(SolutionProperties) = preSolution
68 HideSolutionNode = FALSE
69 EndGlobalSection
70 GlobalSection(ExtensibilityGlobals) = postSolution
71 SolutionGuid = {E4566A6B-47D0-4EA0-989A-D763AC39105D}
72 EndGlobalSection
73EndGlobal
diff --git a/src/ext/Firewall/Firewall.wixext.v3.ncrunchsolution b/src/ext/Firewall/Firewall.wixext.v3.ncrunchsolution
new file mode 100644
index 00000000..10420ac9
--- /dev/null
+++ b/src/ext/Firewall/Firewall.wixext.v3.ncrunchsolution
@@ -0,0 +1,6 @@
1<SolutionConfiguration>
2 <Settings>
3 <AllowParallelTestExecution>True</AllowParallelTestExecution>
4 <SolutionConfigured>True</SolutionConfigured>
5 </Settings>
6</SolutionConfiguration> \ No newline at end of file
diff --git a/src/ext/Firewall/README.md b/src/ext/Firewall/README.md
new file mode 100644
index 00000000..be5801da
--- /dev/null
+++ b/src/ext/Firewall/README.md
@@ -0,0 +1,2 @@
1# Firewall.wixext
2WixToolset.Firewall.wixext - Firewall WiX Toolset Extension
diff --git a/src/ext/Firewall/appveyor.cmd b/src/ext/Firewall/appveyor.cmd
new file mode 100644
index 00000000..79c24cc1
--- /dev/null
+++ b/src/ext/Firewall/appveyor.cmd
@@ -0,0 +1,14 @@
1@setlocal
2@pushd %~dp0
3
4nuget restore || exit /b
5
6msbuild -p:Configuration=Release -t:Restore || exit /b
7
8msbuild -p:Configuration=Release src\test\WixToolsetTest.Firewall\WixToolsetTest.Firewall.csproj || exit /b
9dotnet test -c Release --no-build src\test\WixToolsetTest.Firewall || exit /b
10
11msbuild -p:Configuration=Release -t:Pack src\wixext\WixToolset.Firewall.wixext.csproj || exit /b
12
13@popd
14@endlocal \ No newline at end of file
diff --git a/src/ext/Firewall/appveyor.yml b/src/ext/Firewall/appveyor.yml
new file mode 100644
index 00000000..7c686b04
--- /dev/null
+++ b/src/ext/Firewall/appveyor.yml
@@ -0,0 +1,40 @@
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# Do NOT modify this file. Update the canonical version in Home\repo-template\src\appveyor.yml
4# then update all of the repos.
5
6branches:
7 only:
8 - master
9 - develop
10
11image: Visual Studio 2019
12
13version: 0.0.0.{build}
14configuration: Release
15
16environment:
17 DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
18 DOTNET_CLI_TELEMETRY_OPTOUT: 1
19 NUGET_XMLDOC_MODE: skip
20
21build_script:
22 - appveyor.cmd
23
24pull_requests:
25 do_not_increment_build_number: true
26
27nuget:
28 disable_publish_on_pr: true
29
30skip_branch_with_pr: true
31skip_tags: true
32
33artifacts:
34- path: build\Release\**\*.nupkg
35 name: nuget
36
37notifications:
38- provider: Slack
39 incoming_webhook:
40 secure: p5xuu+4x2JHfwGDMDe5KcG1k7gZxqYc4jWVwvyNZv5cvkubPD2waJs5yXMAXZNN7Z63/3PWHb7q4KoY/99AjauYa1nZ4c5qYqRPFRBKTHfA=
diff --git a/src/ext/Firewall/ca/CustomMsiErrors.h b/src/ext/Firewall/ca/CustomMsiErrors.h
new file mode 100644
index 00000000..f149fb31
--- /dev/null
+++ b/src/ext/Firewall/ca/CustomMsiErrors.h
@@ -0,0 +1,130 @@
1#pragma once
2// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
3
4
5#define GLOBAL_ERROR_BASE 25501
6
7#define msierrSecureObjectsFailedCreateSD 25520
8#define msierrSecureObjectsFailedSet 25521
9#define msierrSecureObjectsUnknownType 25522
10
11#define msierrXmlFileFailedRead 25530
12#define msierrXmlFileFailedOpen 25531
13#define msierrXmlFileFailedSelect 25532
14#define msierrXmlFileFailedSave 25533
15
16#define msierrXmlConfigFailedRead 25540
17#define msierrXmlConfigFailedOpen 25541
18#define msierrXmlConfigFailedSelect 25542
19#define msierrXmlConfigFailedSave 25543
20
21#define msierrFirewallCannotConnect 25580
22
23//---------------------------------------------------------------------------
24// Server CustomAction Errors
25// SERVER range: 26001-26100
26#define SERVER_ERROR_BASE 26000
27
28#define msierrIISCannotConnect 26001
29#define msierrIISFailedReadWebSite 26002
30#define msierrIISFailedReadWebDirs 26003
31#define msierrIISFailedReadVDirs 26004
32#define msierrIISFailedReadFilters 26005
33#define msierrIISFailedReadAppPool 26006
34#define msierrIISFailedReadMimeMap 26007
35#define msierrIISFailedReadProp 26008
36#define msierrIISFailedReadWebSvcExt 26009
37#define msierrIISFailedReadWebError 26010
38#define msierrIISFailedReadHttpHeader 26011
39
40#define msierrIISFailedSchedTransaction 26031
41#define msierrIISFailedSchedInstallWebs 26032
42#define msierrIISFailedSchedInstallWebDirs 26033
43#define msierrIISFailedSchedInstallVDirs 26034
44#define msierrIISFailedSchedInstallFilters 26035
45#define msierrIISFailedSchedInstallAppPool 26036
46#define msierrIISFailedSchedInstallProp 26037
47#define msierrIISFailedSchedInstallWebSvcExt 26038
48
49#define msierrIISFailedSchedUninstallWebs 26051
50#define msierrIISFailedSchedUninstallWebDirs 26052
51#define msierrIISFailedSchedUninstallVDirs 26053
52#define msierrIISFailedSchedUninstallFilters 26054
53#define msierrIISFailedSchedUninstallAppPool 26055
54#define msierrIISFailedSchedUninstallProp 26056
55#define msierrIISFailedSchedUninstallWebSvcExt 26057
56
57#define msierrIISFailedStartTransaction 26101
58#define msierrIISFailedOpenKey 26102
59#define msierrIISFailedCreateKey 26103
60#define msierrIISFailedWriteData 26104
61#define msierrIISFailedCreateApp 26105
62#define msierrIISFailedDeleteKey 26106
63#define msierrIISFailedDeleteApp 26107
64#define msierrIISFailedDeleteValue 26108
65#define msierrIISFailedCommitInUse 26109
66
67#define msierrSQLFailedCreateDatabase 26201
68#define msierrSQLFailedDropDatabase 26202
69#define msierrSQLFailedConnectDatabase 26203
70#define msierrSQLFailedExecString 26204
71#define msierrSQLDatabaseAlreadyExists 26205
72
73#define msierrPERFMONFailedRegisterDLL 26251
74#define msierrPERFMONFailedUnregisterDLL 26252
75#define msierrInstallPerfCounterData 26253
76#define msierrUninstallPerfCounterData 26254
77
78#define msierrSMBFailedCreate 26301
79#define msierrSMBFailedDrop 26302
80
81#define msierrCERTFailedOpen 26351
82#define msierrCERTFailedAdd 26352
83
84#define msierrUSRFailedUserCreate 26401
85#define msierrUSRFailedUserCreatePswd 26402
86#define msierrUSRFailedUserGroupAdd 26403
87#define msierrUSRFailedUserCreateExists 26404
88#define msierrUSRFailedGrantLogonAsService 26405
89
90#define msierrDependencyMissingDependencies 26451
91#define msierrDependencyHasDependents 26452
92
93//--------------------------------------------------------------------------
94// Managed code CustomAction Errors
95// MANAGED range: 27000-27100
96#define MANAGED_ERROR_BASE 27000
97
98#define msierrDotNetRuntimeRequired 27000
99//---------------------------------------------------------------------------
100// Public CustomAction Errors
101// PUBLIC range: 28001-28100
102#define PUBLIC_ERROR_BASE 28000
103
104#define msierrComPlusCannotConnect 28001
105#define msierrComPlusPartitionReadFailed 28002
106#define msierrComPlusPartitionRoleReadFailed 28003
107#define msierrComPlusUserInPartitionRoleReadFailed 28004
108#define msierrComPlusPartitionUserReadFailed 28005
109#define msierrComPlusApplicationReadFailed 28006
110#define msierrComPlusApplicationRoleReadFailed 28007
111#define msierrComPlusUserInApplicationRoleReadFailed 28008
112#define msierrComPlusAssembliesReadFailed 28009
113#define msierrComPlusSubscriptionReadFailed 28010
114#define msierrComPlusPartitionDependency 28011
115#define msierrComPlusPartitionNotFound 28012
116#define msierrComPlusPartitionIdConflict 28013
117#define msierrComPlusPartitionNameConflict 28014
118#define msierrComPlusApplicationDependency 28015
119#define msierrComPlusApplicationNotFound 28016
120#define msierrComPlusApplicationIdConflict 28017
121#define msierrComPlusApplicationNameConflict 28018
122#define msierrComPlusApplicationRoleDependency 28019
123#define msierrComPlusApplicationRoleNotFound 28020
124#define msierrComPlusApplicationRoleConflict 28021
125#define msierrComPlusAssemblyDependency 28022
126#define msierrComPlusSubscriptionIdConflict 28023
127#define msierrComPlusSubscriptionNameConflict 28024
128#define msierrComPlusFailedLookupNames 28025
129
130#define msierrMsmqCannotConnect 28101
diff --git a/src/ext/Firewall/ca/caDecor.h b/src/ext/Firewall/ca/caDecor.h
new file mode 100644
index 00000000..da274650
--- /dev/null
+++ b/src/ext/Firewall/ca/caDecor.h
@@ -0,0 +1,13 @@
1#pragma once
2// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
3
4
5#if defined(_M_ARM64)
6#define CUSTOM_ACTION_DECORATION(f) L"Wix4" f L"_A64"
7#elif defined(_M_AMD64)
8#define CUSTOM_ACTION_DECORATION(f) L"Wix4" f L"_X64"
9#elif defined(_M_ARM)
10#define CUSTOM_ACTION_DECORATION(f) L"Wix4" f L"_ARM"
11#else
12#define CUSTOM_ACTION_DECORATION(f) L"Wix4" f L"_X86"
13#endif
diff --git a/src/ext/Firewall/ca/cost.h b/src/ext/Firewall/ca/cost.h
new file mode 100644
index 00000000..da68c667
--- /dev/null
+++ b/src/ext/Firewall/ca/cost.h
@@ -0,0 +1,5 @@
1#pragma once
2// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
3
4
5const UINT COST_FIREWALL_EXCEPTION = 2000;
diff --git a/src/ext/Firewall/ca/dllmain.cpp b/src/ext/Firewall/ca/dllmain.cpp
new file mode 100644
index 00000000..df53f872
--- /dev/null
+++ b/src/ext/Firewall/ca/dllmain.cpp
@@ -0,0 +1,26 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3#include "precomp.h"
4
5/********************************************************************
6DllMain - standard entry point for all WiX CustomActions
7
8********************************************************************/
9extern "C" BOOL WINAPI DllMain(
10 IN HINSTANCE hInst,
11 IN ULONG ulReason,
12 IN LPVOID)
13{
14 switch(ulReason)
15 {
16 case DLL_PROCESS_ATTACH:
17 WcaGlobalInitialize(hInst);
18 break;
19
20 case DLL_PROCESS_DETACH:
21 WcaGlobalFinalize();
22 break;
23 }
24
25 return TRUE;
26}
diff --git a/src/ext/Firewall/ca/firewall.cpp b/src/ext/Firewall/ca/firewall.cpp
new file mode 100644
index 00000000..caae21a1
--- /dev/null
+++ b/src/ext/Firewall/ca/firewall.cpp
@@ -0,0 +1,1085 @@
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#include "precomp.h"
4
5LPCWSTR vcsFirewallExceptionQuery =
6 L"SELECT `Name`, `RemoteAddresses`, `Port`, `Protocol`, `Program`, `Attributes`, `Profile`, `Component_`, `Description`, `Direction` FROM `Wix4FirewallException`";
7enum eFirewallExceptionQuery { feqName = 1, feqRemoteAddresses, feqPort, feqProtocol, feqProgram, feqAttributes, feqProfile, feqComponent, feqDescription };
8enum eFirewallExceptionTarget { fetPort = 1, fetApplication, fetUnknown };
9enum eFirewallExceptionAttributes { feaIgnoreFailures = 1 };
10
11/******************************************************************
12 SchedFirewallExceptions - immediate custom action worker to
13 register and remove firewall exceptions.
14
15********************************************************************/
16static UINT SchedFirewallExceptions(
17 __in MSIHANDLE hInstall,
18 WCA_TODO todoSched
19 )
20{
21 HRESULT hr = S_OK;
22 UINT er = ERROR_SUCCESS;
23 int cFirewallExceptions = 0;
24
25 PMSIHANDLE hView = NULL;
26 PMSIHANDLE hRec = NULL;
27
28 LPWSTR pwzCustomActionData = NULL;
29 LPWSTR pwzName = NULL;
30 LPWSTR pwzRemoteAddresses = NULL;
31 LPWSTR pwzPort = NULL;
32 int iProtocol = 0;
33 int iAttributes = 0;
34 int iProfile = 0;
35 LPWSTR pwzProgram = NULL;
36 LPWSTR pwzComponent = NULL;
37 LPWSTR pwzFormattedFile = NULL;
38 LPWSTR pwzDescription = NULL;
39 int iDirection = 0;
40
41 // initialize
42 hr = WcaInitialize(hInstall, "SchedFirewallExceptions");
43 ExitOnFailure(hr, "failed to initialize");
44
45 // anything to do?
46 if (S_OK != WcaTableExists(L"Wix4FirewallException"))
47 {
48 WcaLog(LOGMSG_STANDARD, "Wix4FirewallException table doesn't exist, so there are no firewall exceptions to configure.");
49 ExitFunction();
50 }
51
52 // query and loop through all the firewall exceptions
53 hr = WcaOpenExecuteView(vcsFirewallExceptionQuery, &hView);
54 ExitOnFailure(hr, "failed to open view on Wix4FirewallException table");
55
56 while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
57 {
58 hr = WcaGetRecordFormattedString(hRec, feqName, &pwzName);
59 ExitOnFailure(hr, "failed to get firewall exception name");
60
61 hr = WcaGetRecordFormattedString(hRec, feqRemoteAddresses, &pwzRemoteAddresses);
62 ExitOnFailure(hr, "failed to get firewall exception remote addresses");
63
64 hr = WcaGetRecordFormattedString(hRec, feqPort, &pwzPort);
65 ExitOnFailure(hr, "failed to get firewall exception port");
66
67 hr = WcaGetRecordInteger(hRec, feqProtocol, &iProtocol);
68 ExitOnFailure(hr, "failed to get firewall exception protocol");
69
70 hr = WcaGetRecordFormattedString(hRec, feqProgram, &pwzProgram);
71 ExitOnFailure(hr, "failed to get firewall exception program");
72
73 hr = WcaGetRecordInteger(hRec, feqAttributes, &iAttributes);
74 ExitOnFailure(hr, "failed to get firewall exception attributes");
75
76 hr = WcaGetRecordInteger(hRec, feqProfile, &iProfile);
77 ExitOnFailure(hr, "failed to get firewall exception profile");
78
79 hr = WcaGetRecordString(hRec, feqComponent, &pwzComponent);
80 ExitOnFailure(hr, "failed to get firewall exception component");
81
82 hr = WcaGetRecordString(hRec, feqDescription, &pwzDescription);
83 ExitOnFailure(hr, "failed to get firewall description");
84
85 // figure out what we're doing for this exception, treating reinstall the same as install
86 WCA_TODO todoComponent = WcaGetComponentToDo(pwzComponent);
87 if ((WCA_TODO_REINSTALL == todoComponent ? WCA_TODO_INSTALL : todoComponent) != todoSched)
88 {
89 WcaLog(LOGMSG_STANDARD, "Component '%ls' action state (%d) doesn't match request (%d)", pwzComponent, todoComponent, todoSched);
90 continue;
91 }
92
93 // action :: name :: profile :: remoteaddresses :: attributes :: target :: {port::protocol | path}
94 ++cFirewallExceptions;
95 hr = WcaWriteIntegerToCaData(todoComponent, &pwzCustomActionData);
96 ExitOnFailure(hr, "failed to write exception action to custom action data");
97
98 hr = WcaWriteStringToCaData(pwzName, &pwzCustomActionData);
99 ExitOnFailure(hr, "failed to write exception name to custom action data");
100
101 hr = WcaWriteIntegerToCaData(iProfile, &pwzCustomActionData);
102 ExitOnFailure(hr, "failed to write exception profile to custom action data");
103
104 hr = WcaWriteStringToCaData(pwzRemoteAddresses, &pwzCustomActionData);
105 ExitOnFailure(hr, "failed to write exception remote addresses to custom action data");
106
107 hr = WcaWriteIntegerToCaData(iAttributes, &pwzCustomActionData);
108 ExitOnFailure(hr, "failed to write exception attributes to custom action data");
109
110 if (*pwzProgram)
111 {
112 // If program is defined, we have an application exception.
113 hr = WcaWriteIntegerToCaData(fetApplication, &pwzCustomActionData);
114 ExitOnFailure(hr, "failed to write exception target (application) to custom action data");
115
116 hr = WcaWriteStringToCaData(pwzProgram, &pwzCustomActionData);
117 ExitOnFailure(hr, "failed to write application path to custom action data");
118 }
119 else
120 {
121 // we have a port-only exception
122 hr = WcaWriteIntegerToCaData(fetPort, &pwzCustomActionData);
123 ExitOnFailure(hr, "failed to write exception target (port) to custom action data");
124 }
125
126 hr = WcaWriteStringToCaData(pwzPort, &pwzCustomActionData);
127 ExitOnFailure(hr, "failed to write application path to custom action data");
128
129 hr = WcaWriteIntegerToCaData(iProtocol, &pwzCustomActionData);
130 ExitOnFailure(hr, "failed to write exception protocol to custom action data");
131
132 hr = WcaWriteStringToCaData(pwzDescription, &pwzCustomActionData);
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");
137 }
138
139 // reaching the end of the list is actually a good thing, not an error
140 if (E_NOMOREITEMS == hr)
141 {
142 hr = S_OK;
143 }
144 ExitOnFailure(hr, "failure occured while processing Wix4FirewallException table");
145
146 // schedule ExecFirewallExceptions if there's anything to do
147 if (pwzCustomActionData && *pwzCustomActionData)
148 {
149 WcaLog(LOGMSG_STANDARD, "Scheduling firewall exception (%ls)", pwzCustomActionData);
150
151 if (WCA_TODO_INSTALL == todoSched)
152 {
153 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackFirewallExceptionsInstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
154 ExitOnFailure(hr, "failed to schedule firewall install exceptions rollback");
155 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecFirewallExceptionsInstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
156 ExitOnFailure(hr, "failed to schedule firewall install exceptions execution");
157 }
158 else
159 {
160 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackFirewallExceptionsUninstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
161 ExitOnFailure(hr, "failed to schedule firewall uninstall exceptions rollback");
162 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecFirewallExceptionsUninstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION);
163 ExitOnFailure(hr, "failed to schedule firewall uninstall exceptions execution");
164 }
165 }
166 else
167 {
168 WcaLog(LOGMSG_STANDARD, "No firewall exceptions scheduled");
169 }
170
171LExit:
172 ReleaseStr(pwzCustomActionData);
173 ReleaseStr(pwzName);
174 ReleaseStr(pwzRemoteAddresses);
175 ReleaseStr(pwzPort);
176 ReleaseStr(pwzProgram);
177 ReleaseStr(pwzComponent);
178 ReleaseStr(pwzDescription);
179 ReleaseStr(pwzFormattedFile);
180
181 return WcaFinalize(er = FAILED(hr) ? ERROR_INSTALL_FAILURE : er);
182}
183
184/******************************************************************
185 SchedFirewallExceptionsInstall - immediate custom action entry
186 point to register firewall exceptions.
187
188********************************************************************/
189extern "C" UINT __stdcall SchedFirewallExceptionsInstall(
190 __in MSIHANDLE hInstall
191 )
192{
193 return SchedFirewallExceptions(hInstall, WCA_TODO_INSTALL);
194}
195
196/******************************************************************
197 SchedFirewallExceptionsUninstall - immediate custom action entry
198 point to remove firewall exceptions.
199
200********************************************************************/
201extern "C" UINT __stdcall SchedFirewallExceptionsUninstall(
202 __in MSIHANDLE hInstall
203 )
204{
205 return SchedFirewallExceptions(hInstall, WCA_TODO_UNINSTALL);
206}
207
208/******************************************************************
209 GetFirewallRules - Get the collection of firewall rules.
210
211********************************************************************/
212static HRESULT GetFirewallRules(
213 __in BOOL fIgnoreFailures,
214 __out INetFwRules** ppNetFwRules
215 )
216{
217 HRESULT hr = S_OK;
218 INetFwPolicy2* pNetFwPolicy2 = NULL;
219 INetFwRules* pNetFwRules = NULL;
220 *ppNetFwRules = NULL;
221
222 do
223 {
224 ReleaseNullObject(pNetFwPolicy2);
225 ReleaseNullObject(pNetFwRules);
226
227 if (SUCCEEDED(hr = ::CoCreateInstance(__uuidof(NetFwPolicy2), NULL, CLSCTX_ALL, __uuidof(INetFwPolicy2), (void**)&pNetFwPolicy2)) &&
228 SUCCEEDED(hr = pNetFwPolicy2->get_Rules(&pNetFwRules)))
229 {
230 break;
231 }
232 else if (fIgnoreFailures)
233 {
234 ExitFunction1(hr = S_FALSE);
235 }
236 else
237 {
238 WcaLog(LOGMSG_STANDARD, "Failed to connect to Windows Firewall");
239 UINT er = WcaErrorMessage(msierrFirewallCannotConnect, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
240 switch (er)
241 {
242 case IDABORT: // exit with the current HRESULT
243 ExitFunction();
244 case IDRETRY: // clean up and retry the loop
245 hr = S_FALSE;
246 break;
247 case IDIGNORE: // pass S_FALSE back to the caller, who knows how to ignore the failure
248 ExitFunction1(hr = S_FALSE);
249 default: // No UI, so default is to fail.
250 ExitFunction();
251 }
252 }
253 } while (S_FALSE == hr);
254
255 *ppNetFwRules = pNetFwRules;
256 pNetFwRules = NULL;
257
258LExit:
259 ReleaseObject(pNetFwPolicy2);
260 ReleaseObject(pNetFwRules);
261
262 return hr;
263}
264
265/******************************************************************
266 CreateFwRuleObject - CoCreate a firewall rule, and set the common set of properties which are shared
267 between port and application firewall rules
268
269********************************************************************/
270static HRESULT CreateFwRuleObject(
271 __in BSTR bstrName,
272 __in int iProfile,
273 __in_opt LPCWSTR wzRemoteAddresses,
274 __in LPCWSTR wzPort,
275 __in int iProtocol,
276 __in LPCWSTR wzDescription,
277 __in int iDirection,
278 __out INetFwRule** ppNetFwRule
279 )
280{
281 HRESULT hr = S_OK;
282 BSTR bstrRemoteAddresses = NULL;
283 BSTR bstrPort = NULL;
284 BSTR bstrDescription = NULL;
285 INetFwRule* pNetFwRule = NULL;
286 *ppNetFwRule = NULL;
287
288 // convert to BSTRs to make COM happy
289 bstrRemoteAddresses = ::SysAllocString(wzRemoteAddresses);
290 ExitOnNull(bstrRemoteAddresses, hr, E_OUTOFMEMORY, "failed SysAllocString for remote addresses");
291 bstrPort = ::SysAllocString(wzPort);
292 ExitOnNull(bstrPort, hr, E_OUTOFMEMORY, "failed SysAllocString for port");
293 bstrDescription = ::SysAllocString(wzDescription);
294 ExitOnNull(bstrDescription, hr, E_OUTOFMEMORY, "failed SysAllocString for description");
295
296 hr = ::CoCreateInstance(__uuidof(NetFwRule), NULL, CLSCTX_ALL, __uuidof(INetFwRule), (void**)&pNetFwRule);
297 ExitOnFailure(hr, "failed to create NetFwRule object");
298
299 hr = pNetFwRule->put_Name(bstrName);
300 ExitOnFailure(hr, "failed to set exception name");
301
302 hr = pNetFwRule->put_Profiles(static_cast<NET_FW_PROFILE_TYPE2>(iProfile));
303 ExitOnFailure(hr, "failed to set exception profile");
304
305 if (MSI_NULL_INTEGER != iProtocol)
306 {
307 hr = pNetFwRule->put_Protocol(static_cast<NET_FW_IP_PROTOCOL>(iProtocol));
308 ExitOnFailure(hr, "failed to set exception protocol");
309 }
310
311 if (bstrPort && *bstrPort)
312 {
313 hr = pNetFwRule->put_LocalPorts(bstrPort);
314 ExitOnFailure(hr, "failed to set exception port");
315 }
316
317 if (bstrRemoteAddresses && *bstrRemoteAddresses)
318 {
319 hr = pNetFwRule->put_RemoteAddresses(bstrRemoteAddresses);
320 ExitOnFailure(hr, "failed to set exception remote addresses '%ls'", bstrRemoteAddresses);
321 }
322
323 if (bstrDescription && *bstrDescription)
324 {
325 hr = pNetFwRule->put_Description(bstrDescription);
326 ExitOnFailure(hr, "failed to set exception description '%ls'", bstrDescription);
327 }
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
335 *ppNetFwRule = pNetFwRule;
336 pNetFwRule = NULL;
337
338LExit:
339 ReleaseBSTR(bstrRemoteAddresses);
340 ReleaseBSTR(bstrPort);
341 ReleaseBSTR(bstrDescription);
342 ReleaseObject(pNetFwRule);
343
344 return hr;
345}
346
347/******************************************************************
348 FSupportProfiles - Returns true if we support profiles on this machine.
349 (Only on Vista or later)
350
351********************************************************************/
352static BOOL FSupportProfiles()
353{
354 BOOL fSupportProfiles = FALSE;
355 INetFwRules* pNetFwRules = NULL;
356
357 // We only support profiles if we can co-create an instance of NetFwPolicy2.
358 // This will not work on pre-vista machines.
359 if (SUCCEEDED(GetFirewallRules(TRUE, &pNetFwRules)) && pNetFwRules != NULL)
360 {
361 fSupportProfiles = TRUE;
362 ReleaseObject(pNetFwRules);
363 }
364
365 return fSupportProfiles;
366}
367
368/******************************************************************
369 GetCurrentFirewallProfile - get the active firewall profile as an
370 INetFwProfile, which owns the lists of exceptions we're
371 updating.
372
373********************************************************************/
374static HRESULT GetCurrentFirewallProfile(
375 __in BOOL fIgnoreFailures,
376 __out INetFwProfile** ppfwProfile
377 )
378{
379 HRESULT hr = S_OK;
380 INetFwMgr* pfwMgr = NULL;
381 INetFwPolicy* pfwPolicy = NULL;
382 INetFwProfile* pfwProfile = NULL;
383 *ppfwProfile = NULL;
384
385 do
386 {
387 ReleaseNullObject(pfwPolicy);
388 ReleaseNullObject(pfwMgr);
389 ReleaseNullObject(pfwProfile);
390
391 if (SUCCEEDED(hr = ::CoCreateInstance(__uuidof(NetFwMgr), NULL, CLSCTX_INPROC_SERVER, __uuidof(INetFwMgr), (void**)&pfwMgr)) &&
392 SUCCEEDED(hr = pfwMgr->get_LocalPolicy(&pfwPolicy)) &&
393 SUCCEEDED(hr = pfwPolicy->get_CurrentProfile(&pfwProfile)))
394 {
395 break;
396 }
397 else if (fIgnoreFailures)
398 {
399 ExitFunction1(hr = S_FALSE);
400 }
401 else
402 {
403 WcaLog(LOGMSG_STANDARD, "Failed to connect to Windows Firewall");
404 UINT er = WcaErrorMessage(msierrFirewallCannotConnect, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0);
405 switch (er)
406 {
407 case IDABORT: // exit with the current HRESULT
408 ExitFunction();
409 case IDRETRY: // clean up and retry the loop
410 hr = S_FALSE;
411 break;
412 case IDIGNORE: // pass S_FALSE back to the caller, who knows how to ignore the failure
413 ExitFunction1(hr = S_FALSE);
414 default: // No UI, so default is to fail.
415 ExitFunction();
416 }
417 }
418 } while (S_FALSE == hr);
419
420 *ppfwProfile = pfwProfile;
421 pfwProfile = NULL;
422
423LExit:
424 ReleaseObject(pfwPolicy);
425 ReleaseObject(pfwMgr);
426 ReleaseObject(pfwProfile);
427
428 return hr;
429}
430
431/******************************************************************
432 AddApplicationException
433
434********************************************************************/
435static HRESULT AddApplicationException(
436 __in LPCWSTR wzFile,
437 __in LPCWSTR wzName,
438 __in int iProfile,
439 __in_opt LPCWSTR wzRemoteAddresses,
440 __in BOOL fIgnoreFailures,
441 __in LPCWSTR wzPort,
442 __in int iProtocol,
443 __in LPCWSTR wzDescription,
444 __in int iDirection
445 )
446{
447 HRESULT hr = S_OK;
448 BSTR bstrFile = NULL;
449 BSTR bstrName = NULL;
450 INetFwRules* pNetFwRules = NULL;
451 INetFwRule* pNetFwRule = NULL;
452
453 // convert to BSTRs to make COM happy
454 bstrFile = ::SysAllocString(wzFile);
455 ExitOnNull(bstrFile, hr, E_OUTOFMEMORY, "failed SysAllocString for path");
456 bstrName = ::SysAllocString(wzName);
457 ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "failed SysAllocString for name");
458
459 // get the collection of firewall rules
460 hr = GetFirewallRules(fIgnoreFailures, &pNetFwRules);
461 ExitOnFailure(hr, "failed to get firewall rules object");
462 if (S_FALSE == hr) // user or package author chose to ignore missing firewall
463 {
464 ExitFunction();
465 }
466
467 // try to find it (i.e., support reinstall)
468 hr = pNetFwRules->Item(bstrName, &pNetFwRule);
469 if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
470 {
471 hr = CreateFwRuleObject(bstrName, iProfile, wzRemoteAddresses, wzPort, iProtocol, wzDescription, iDirection, &pNetFwRule);
472 ExitOnFailure(hr, "failed to create FwRule object");
473
474 // set edge traversal to true
475 hr = pNetFwRule->put_EdgeTraversal(VARIANT_TRUE);
476 ExitOnFailure(hr, "failed to set application exception edgetraversal property");
477
478 // set path
479 hr = pNetFwRule->put_ApplicationName(bstrFile);
480 ExitOnFailure(hr, "failed to set application name");
481
482 // enable it
483 hr = pNetFwRule->put_Enabled(VARIANT_TRUE);
484 ExitOnFailure(hr, "failed to to enable application exception");
485
486 // add it to the list of authorized apps
487 hr = pNetFwRules->Add(pNetFwRule);
488 ExitOnFailure(hr, "failed to add app to the authorized apps list");
489 }
490 else
491 {
492 // we found an existing app exception (if we succeeded, that is)
493 ExitOnFailure(hr, "failed trying to find existing app");
494
495 // enable it (just in case it was disabled)
496 pNetFwRule->put_Enabled(VARIANT_TRUE);
497 }
498
499LExit:
500 ReleaseBSTR(bstrName);
501 ReleaseBSTR(bstrFile);
502 ReleaseObject(pNetFwRules);
503 ReleaseObject(pNetFwRule);
504
505 return fIgnoreFailures ? S_OK : hr;
506}
507
508/******************************************************************
509 AddApplicationExceptionOnCurrentProfile
510
511********************************************************************/
512static HRESULT AddApplicationExceptionOnCurrentProfile(
513 __in LPCWSTR wzFile,
514 __in LPCWSTR wzName,
515 __in_opt LPCWSTR wzRemoteAddresses,
516 __in BOOL fIgnoreFailures
517 )
518{
519 HRESULT hr = S_OK;
520 BSTR bstrFile = NULL;
521 BSTR bstrName = NULL;
522 BSTR bstrRemoteAddresses = NULL;
523 INetFwProfile* pfwProfile = NULL;
524 INetFwAuthorizedApplications* pfwApps = NULL;
525 INetFwAuthorizedApplication* pfwApp = NULL;
526
527 // convert to BSTRs to make COM happy
528 bstrFile = ::SysAllocString(wzFile);
529 ExitOnNull(bstrFile, hr, E_OUTOFMEMORY, "failed SysAllocString for path");
530 bstrName = ::SysAllocString(wzName);
531 ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "failed SysAllocString for name");
532 bstrRemoteAddresses = ::SysAllocString(wzRemoteAddresses);
533 ExitOnNull(bstrRemoteAddresses, hr, E_OUTOFMEMORY, "failed SysAllocString for remote addresses");
534
535 // get the firewall profile, which is our entry point for adding exceptions
536 hr = GetCurrentFirewallProfile(fIgnoreFailures, &pfwProfile);
537 ExitOnFailure(hr, "failed to get firewall profile");
538 if (S_FALSE == hr) // user or package author chose to ignore missing firewall
539 {
540 ExitFunction();
541 }
542
543 // first, let's see if the app is already on the exception list
544 hr = pfwProfile->get_AuthorizedApplications(&pfwApps);
545 ExitOnFailure(hr, "failed to get list of authorized apps");
546
547 // try to find it (i.e., support reinstall)
548 hr = pfwApps->Item(bstrFile, &pfwApp);
549 if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
550 {
551 // not found, so we get to add it
552 hr = ::CoCreateInstance(__uuidof(NetFwAuthorizedApplication), NULL, CLSCTX_INPROC_SERVER, __uuidof(INetFwAuthorizedApplication), reinterpret_cast<void**>(&pfwApp));
553 ExitOnFailure(hr, "failed to create authorized app");
554
555 // set the display name
556 hr = pfwApp->put_Name(bstrName);
557 ExitOnFailure(hr, "failed to set authorized app name");
558
559 // set path
560 hr = pfwApp->put_ProcessImageFileName(bstrFile);
561 ExitOnFailure(hr, "failed to set authorized app path");
562
563 // set the allowed remote addresses
564 if (bstrRemoteAddresses && *bstrRemoteAddresses)
565 {
566 hr = pfwApp->put_RemoteAddresses(bstrRemoteAddresses);
567 ExitOnFailure(hr, "failed to set authorized app remote addresses");
568 }
569
570 // add it to the list of authorized apps
571 hr = pfwApps->Add(pfwApp);
572 ExitOnFailure(hr, "failed to add app to the authorized apps list");
573 }
574 else
575 {
576 // we found an existing app exception (if we succeeded, that is)
577 ExitOnFailure(hr, "failed trying to find existing app");
578
579 // enable it (just in case it was disabled)
580 pfwApp->put_Enabled(VARIANT_TRUE);
581 }
582
583LExit:
584 ReleaseBSTR(bstrRemoteAddresses);
585 ReleaseBSTR(bstrName);
586 ReleaseBSTR(bstrFile);
587 ReleaseObject(pfwApp);
588 ReleaseObject(pfwApps);
589 ReleaseObject(pfwProfile);
590
591 return fIgnoreFailures ? S_OK : hr;
592}
593
594/******************************************************************
595 AddPortException
596
597********************************************************************/
598static HRESULT AddPortException(
599 __in LPCWSTR wzName,
600 __in int iProfile,
601 __in_opt LPCWSTR wzRemoteAddresses,
602 __in BOOL fIgnoreFailures,
603 __in LPCWSTR wzPort,
604 __in int iProtocol,
605 __in LPCWSTR wzDescription,
606 __in int iDirection
607)
608{
609 HRESULT hr = S_OK;
610 BSTR bstrName = NULL;
611 INetFwRules* pNetFwRules = NULL;
612 INetFwRule* pNetFwRule = NULL;
613
614 // convert to BSTRs to make COM happy
615 bstrName = ::SysAllocString(wzName);
616 ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "failed SysAllocString for name");
617
618 // get the collection of firewall rules
619 hr = GetFirewallRules(fIgnoreFailures, &pNetFwRules);
620 ExitOnFailure(hr, "failed to get firewall rules object");
621 if (S_FALSE == hr) // user or package author chose to ignore missing firewall
622 {
623 ExitFunction();
624 }
625
626 // try to find it (i.e., support reinstall)
627 hr = pNetFwRules->Item(bstrName, &pNetFwRule);
628 if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr)
629 {
630 hr = CreateFwRuleObject(bstrName, iProfile, wzRemoteAddresses, wzPort, iProtocol, wzDescription, iDirection, &pNetFwRule);
631 ExitOnFailure(hr, "failed to create FwRule object");
632
633 // enable it
634 hr = pNetFwRule->put_Enabled(VARIANT_TRUE);
635 ExitOnFailure(hr, "failed to to enable port exception");
636
637 // add it to the list of authorized ports
638 hr = pNetFwRules->Add(pNetFwRule);
639 ExitOnFailure(hr, "failed to add app to the authorized ports list");
640 }
641 else
642 {
643 // we found an existing port exception (if we succeeded, that is)
644 ExitOnFailure(hr, "failed trying to find existing port rule");
645
646 // enable it (just in case it was disabled)
647 pNetFwRule->put_Enabled(VARIANT_TRUE);
648 }
649
650LExit:
651 ReleaseBSTR(bstrName);
652 ReleaseObject(pNetFwRules);
653 ReleaseObject(pNetFwRule);
654
655 return fIgnoreFailures ? S_OK : hr;
656}
657
658/******************************************************************
659 AddPortExceptionOnCurrentProfile
660
661********************************************************************/
662static HRESULT AddPortExceptionOnCurrentProfile(
663 __in LPCWSTR wzName,
664 __in_opt LPCWSTR wzRemoteAddresses,
665 __in BOOL fIgnoreFailures,
666 __in int iPort,
667 __in int iProtocol
668 )
669{
670 HRESULT hr = S_OK;
671 BSTR bstrName = NULL;
672 BSTR bstrRemoteAddresses = NULL;
673 INetFwProfile* pfwProfile = NULL;
674 INetFwOpenPorts* pfwPorts = NULL;
675 INetFwOpenPort* pfwPort = NULL;
676
677 // convert to BSTRs to make COM happy
678 bstrName = ::SysAllocString(wzName);
679 ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "failed SysAllocString for name");
680 bstrRemoteAddresses = ::SysAllocString(wzRemoteAddresses);
681 ExitOnNull(bstrRemoteAddresses, hr, E_OUTOFMEMORY, "failed SysAllocString for remote addresses");
682
683 // create and initialize a new open port object
684 hr = ::CoCreateInstance(__uuidof(NetFwOpenPort), NULL, CLSCTX_INPROC_SERVER, __uuidof(INetFwOpenPort), reinterpret_cast<void**>(&pfwPort));
685 ExitOnFailure(hr, "failed to create new open port");
686
687 hr = pfwPort->put_Port(iPort);
688 ExitOnFailure(hr, "failed to set exception port");
689
690 hr = pfwPort->put_Protocol(static_cast<NET_FW_IP_PROTOCOL>(iProtocol));
691 ExitOnFailure(hr, "failed to set exception protocol");
692
693 if (bstrRemoteAddresses && *bstrRemoteAddresses)
694 {
695 hr = pfwPort->put_RemoteAddresses(bstrRemoteAddresses);
696 ExitOnFailure(hr, "failed to set exception remote addresses '%ls'", bstrRemoteAddresses);
697 }
698
699 hr = pfwPort->put_Name(bstrName);
700 ExitOnFailure(hr, "failed to set exception name");
701
702 // get the firewall profile, its current list of open ports, and add ours
703 hr = GetCurrentFirewallProfile(fIgnoreFailures, &pfwProfile);
704 ExitOnFailure(hr, "failed to get firewall profile");
705 if (S_FALSE == hr) // user or package author chose to ignore missing firewall
706 {
707 ExitFunction();
708 }
709
710 hr = pfwProfile->get_GloballyOpenPorts(&pfwPorts);
711 ExitOnFailure(hr, "failed to get open ports");
712
713 hr = pfwPorts->Add(pfwPort);
714 ExitOnFailure(hr, "failed to add exception to global list");
715
716LExit:
717 ReleaseBSTR(bstrRemoteAddresses);
718 ReleaseBSTR(bstrName);
719 ReleaseObject(pfwProfile);
720 ReleaseObject(pfwPorts);
721 ReleaseObject(pfwPort);
722
723 return fIgnoreFailures ? S_OK : hr;
724}
725
726/******************************************************************
727 RemoveException - Removes the exception rule with the given name.
728
729********************************************************************/
730static HRESULT RemoveException(
731 __in LPCWSTR wzName,
732 __in BOOL fIgnoreFailures
733 )
734{
735 HRESULT hr = S_OK;;
736 INetFwRules* pNetFwRules = NULL;
737
738 // convert to BSTRs to make COM happy
739 BSTR bstrName = ::SysAllocString(wzName);
740 ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "failed SysAllocString for path");
741
742 // get the collection of firewall rules
743 hr = GetFirewallRules(fIgnoreFailures, &pNetFwRules);
744 ExitOnFailure(hr, "failed to get firewall rules object");
745 if (S_FALSE == hr) // user or package author chose to ignore missing firewall
746 {
747 ExitFunction();
748 }
749
750 hr = pNetFwRules->Remove(bstrName);
751 ExitOnFailure(hr, "failed to remove authorized app");
752
753LExit:
754 ReleaseBSTR(bstrName);
755 ReleaseObject(pNetFwRules);
756
757 return fIgnoreFailures ? S_OK : hr;
758}
759
760/******************************************************************
761 RemoveApplicationExceptionFromCurrentProfile
762
763********************************************************************/
764static HRESULT RemoveApplicationExceptionFromCurrentProfile(
765 __in LPCWSTR wzFile,
766 __in BOOL fIgnoreFailures
767 )
768{
769 HRESULT hr = S_OK;
770 INetFwProfile* pfwProfile = NULL;
771 INetFwAuthorizedApplications* pfwApps = NULL;
772
773 // convert to BSTRs to make COM happy
774 BSTR bstrFile = ::SysAllocString(wzFile);
775 ExitOnNull(bstrFile, hr, E_OUTOFMEMORY, "failed SysAllocString for path");
776
777 // get the firewall profile, which is our entry point for removing exceptions
778 hr = GetCurrentFirewallProfile(fIgnoreFailures, &pfwProfile);
779 ExitOnFailure(hr, "failed to get firewall profile");
780 if (S_FALSE == hr) // user or package author chose to ignore missing firewall
781 {
782 ExitFunction();
783 }
784
785 // now get the list of app exceptions and remove the one
786 hr = pfwProfile->get_AuthorizedApplications(&pfwApps);
787 ExitOnFailure(hr, "failed to get list of authorized apps");
788
789 hr = pfwApps->Remove(bstrFile);
790 ExitOnFailure(hr, "failed to remove authorized app");
791
792LExit:
793 ReleaseBSTR(bstrFile);
794 ReleaseObject(pfwApps);
795 ReleaseObject(pfwProfile);
796
797 return fIgnoreFailures ? S_OK : hr;
798}
799
800/******************************************************************
801 RemovePortExceptionFromCurrentProfile
802
803********************************************************************/
804static HRESULT RemovePortExceptionFromCurrentProfile(
805 __in int iPort,
806 __in int iProtocol,
807 __in BOOL fIgnoreFailures
808 )
809{
810 HRESULT hr = S_OK;
811 INetFwProfile* pfwProfile = NULL;
812 INetFwOpenPorts* pfwPorts = NULL;
813
814 // get the firewall profile, which is our entry point for adding exceptions
815 hr = GetCurrentFirewallProfile(fIgnoreFailures, &pfwProfile);
816 ExitOnFailure(hr, "failed to get firewall profile");
817 if (S_FALSE == hr) // user or package author chose to ignore missing firewall
818 {
819 ExitFunction();
820 }
821
822 hr = pfwProfile->get_GloballyOpenPorts(&pfwPorts);
823 ExitOnFailure(hr, "failed to get open ports");
824
825 hr = pfwPorts->Remove(iPort, static_cast<NET_FW_IP_PROTOCOL>(iProtocol));
826 ExitOnFailure(hr, "failed to remove open port %d, protocol %d", iPort, iProtocol);
827
828LExit:
829 return fIgnoreFailures ? S_OK : hr;
830}
831
832static HRESULT AddApplicationException(
833 __in BOOL fSupportProfiles,
834 __in LPCWSTR wzFile,
835 __in LPCWSTR wzName,
836 __in int iProfile,
837 __in_opt LPCWSTR wzRemoteAddresses,
838 __in BOOL fIgnoreFailures,
839 __in LPCWSTR wzPort,
840 __in int iProtocol,
841 __in LPCWSTR wzDescription,
842 __in int iDirection
843)
844{
845 HRESULT hr = S_OK;
846
847 if (fSupportProfiles)
848 {
849 hr = AddApplicationException(wzFile, wzName, iProfile, wzRemoteAddresses, fIgnoreFailures, wzPort, iProtocol, wzDescription, iDirection);
850 }
851 else
852 {
853 if (0 != *wzPort || MSI_NULL_INTEGER != iProtocol)
854 {
855 // NOTE: This is treated as an error rather than either creating a rule based on just the application (no port), or
856 // just the port because it is unclear what is the proper fall back. For example, suppose that you have code that
857 // runs in dllhost.exe. Clearly falling back to opening all of dllhost is wrong. Because the firewall is a security
858 // feature, it seems better to require the MSI author to indicate the behavior that they want.
859 WcaLog(LOGMSG_STANDARD, "FirewallExtension: Cannot add firewall rule '%ls', which defines both an application and a port or protocol. Such a rule requires Microsoft Windows Vista or later.", wzName);
860 return fIgnoreFailures ? S_OK : E_NOTIMPL;
861 }
862
863 hr = AddApplicationExceptionOnCurrentProfile(wzFile, wzName, wzRemoteAddresses, fIgnoreFailures);
864 }
865
866 return hr;
867}
868
869static HRESULT AddPortException(
870 __in BOOL fSupportProfiles,
871 __in LPCWSTR wzName,
872 __in int iProfile,
873 __in_opt LPCWSTR wzRemoteAddresses,
874 __in BOOL fIgnoreFailures,
875 __in LPCWSTR wzPort,
876 __in int iProtocol,
877 __in LPCWSTR wzDescription,
878 __in int iDirection
879)
880{
881 HRESULT hr = S_OK;
882
883 if (fSupportProfiles)
884 {
885 hr = AddPortException(wzName, iProfile, wzRemoteAddresses, fIgnoreFailures, wzPort, iProtocol, wzDescription, iDirection);
886 }
887 else
888 {
889 hr = AddPortExceptionOnCurrentProfile(wzName, wzRemoteAddresses, fIgnoreFailures, wcstol(wzPort, NULL, 10), iProtocol);
890 }
891
892 return hr;
893}
894
895static HRESULT RemoveApplicationException(
896 __in BOOL fSupportProfiles,
897 __in LPCWSTR wzName,
898 __in LPCWSTR wzFile,
899 __in BOOL fIgnoreFailures,
900 __in LPCWSTR wzPort,
901 __in int iProtocol
902 )
903{
904 HRESULT hr = S_OK;
905
906 if (fSupportProfiles)
907 {
908 hr = RemoveException(wzName, fIgnoreFailures);
909 }
910 else
911 {
912 if (0 != *wzPort || MSI_NULL_INTEGER != iProtocol)
913 {
914 WcaLog(LOGMSG_STANDARD, "FirewallExtension: Cannot remove firewall rule '%ls', which defines both an application and a port or protocol. Such a rule requires Microsoft Windows Vista or later.", wzName);
915 return S_OK;
916 }
917
918 hr = RemoveApplicationExceptionFromCurrentProfile(wzFile, fIgnoreFailures);
919 }
920
921 return hr;
922}
923
924static HRESULT RemovePortException(
925 __in BOOL fSupportProfiles,
926 __in LPCWSTR wzName,
927 __in LPCWSTR wzPort,
928 __in int iProtocol,
929 __in BOOL fIgnoreFailures
930 )
931{
932 HRESULT hr = S_OK;
933
934 if (fSupportProfiles)
935 {
936 hr = RemoveException(wzName, fIgnoreFailures);
937 }
938 else
939 {
940 hr = RemovePortExceptionFromCurrentProfile(wcstol(wzPort, NULL, 10), iProtocol, fIgnoreFailures);
941 }
942
943 return hr;
944}
945
946/******************************************************************
947 ExecFirewallExceptions - deferred custom action entry point to
948 register and remove firewall exceptions.
949
950********************************************************************/
951extern "C" UINT __stdcall ExecFirewallExceptions(
952 __in MSIHANDLE hInstall
953 )
954{
955 HRESULT hr = S_OK;
956 BOOL fSupportProfiles = FALSE;
957 LPWSTR pwz = NULL;
958 LPWSTR pwzCustomActionData = NULL;
959 int iTodo = WCA_TODO_UNKNOWN;
960 LPWSTR pwzName = NULL;
961 LPWSTR pwzRemoteAddresses = NULL;
962 int iAttributes = 0;
963 int iTarget = fetUnknown;
964 LPWSTR pwzFile = NULL;
965 LPWSTR pwzPort = NULL;
966 LPWSTR pwzDescription = NULL;
967 int iProtocol = 0;
968 int iProfile = 0;
969 int iDirection = 0;
970
971 // initialize
972 hr = WcaInitialize(hInstall, "ExecFirewallExceptions");
973 ExitOnFailure(hr, "failed to initialize");
974
975 hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData);
976 ExitOnFailure(hr, "failed to get CustomActionData");
977 WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData);
978
979 hr = ::CoInitialize(NULL);
980 ExitOnFailure(hr, "failed to initialize COM");
981
982 // Find out if we support profiles (only on Vista or later)
983 fSupportProfiles = FSupportProfiles();
984
985 // loop through all the passed in data
986 pwz = pwzCustomActionData;
987 while (pwz && *pwz)
988 {
989 // extract the custom action data and if rolling back, swap INSTALL and UNINSTALL
990 hr = WcaReadIntegerFromCaData(&pwz, &iTodo);
991 ExitOnFailure(hr, "failed to read todo from custom action data");
992 if (::MsiGetMode(hInstall, MSIRUNMODE_ROLLBACK))
993 {
994 if (WCA_TODO_INSTALL == iTodo)
995 {
996 iTodo = WCA_TODO_UNINSTALL;
997 }
998 else if (WCA_TODO_UNINSTALL == iTodo)
999 {
1000 iTodo = WCA_TODO_INSTALL;
1001 }
1002 }
1003
1004 hr = WcaReadStringFromCaData(&pwz, &pwzName);
1005 ExitOnFailure(hr, "failed to read name from custom action data");
1006
1007 hr = WcaReadIntegerFromCaData(&pwz, &iProfile);
1008 ExitOnFailure(hr, "failed to read profile from custom action data");
1009
1010 hr = WcaReadStringFromCaData(&pwz, &pwzRemoteAddresses);
1011 ExitOnFailure(hr, "failed to read remote addresses from custom action data");
1012
1013 hr = WcaReadIntegerFromCaData(&pwz, &iAttributes);
1014 ExitOnFailure(hr, "failed to read attributes from custom action data");
1015 BOOL fIgnoreFailures = feaIgnoreFailures == (iAttributes & feaIgnoreFailures);
1016
1017 hr = WcaReadIntegerFromCaData(&pwz, &iTarget);
1018 ExitOnFailure(hr, "failed to read target from custom action data");
1019
1020 if (iTarget == fetApplication)
1021 {
1022 hr = WcaReadStringFromCaData(&pwz, &pwzFile);
1023 ExitOnFailure(hr, "failed to read file path from custom action data");
1024 }
1025
1026 hr = WcaReadStringFromCaData(&pwz, &pwzPort);
1027 ExitOnFailure(hr, "failed to read port from custom action data");
1028 hr = WcaReadIntegerFromCaData(&pwz, &iProtocol);
1029 ExitOnFailure(hr, "failed to read protocol from custom action data");
1030 hr = WcaReadStringFromCaData(&pwz, &pwzDescription);
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");
1034
1035 switch (iTarget)
1036 {
1037 case fetPort:
1038 switch (iTodo)
1039 {
1040 case WCA_TODO_INSTALL:
1041 case WCA_TODO_REINSTALL:
1042 WcaLog(LOGMSG_STANDARD, "Installing firewall exception2 %ls on port %ls, protocol %d", pwzName, pwzPort, iProtocol);
1043 hr = AddPortException(fSupportProfiles, pwzName, iProfile, pwzRemoteAddresses, fIgnoreFailures, pwzPort, iProtocol, pwzDescription, iDirection);
1044 ExitOnFailure(hr, "failed to add/update port exception for name '%ls' on port %ls, protocol %d", pwzName, pwzPort, iProtocol);
1045 break;
1046
1047 case WCA_TODO_UNINSTALL:
1048 WcaLog(LOGMSG_STANDARD, "Uninstalling firewall exception2 %ls on port %ls, protocol %d", pwzName, pwzPort, iProtocol);
1049 hr = RemovePortException(fSupportProfiles, pwzName, pwzPort, iProtocol, fIgnoreFailures);
1050 ExitOnFailure(hr, "failed to remove port exception for name '%ls' on port %ls, protocol %d", pwzName, pwzPort, iProtocol);
1051 break;
1052 }
1053 break;
1054
1055 case fetApplication:
1056 switch (iTodo)
1057 {
1058 case WCA_TODO_INSTALL:
1059 case WCA_TODO_REINSTALL:
1060 WcaLog(LOGMSG_STANDARD, "Installing firewall exception2 %ls (%ls)", pwzName, pwzFile);
1061 hr = AddApplicationException(fSupportProfiles, pwzFile, pwzName, iProfile, pwzRemoteAddresses, fIgnoreFailures, pwzPort, iProtocol, pwzDescription, iDirection);
1062 ExitOnFailure(hr, "failed to add/update application exception for name '%ls', file '%ls'", pwzName, pwzFile);
1063 break;
1064
1065 case WCA_TODO_UNINSTALL:
1066 WcaLog(LOGMSG_STANDARD, "Uninstalling firewall exception2 %ls (%ls)", pwzName, pwzFile);
1067 hr = RemoveApplicationException(fSupportProfiles, pwzName, pwzFile, fIgnoreFailures, pwzPort, iProtocol);
1068 ExitOnFailure(hr, "failed to remove application exception for name '%ls', file '%ls'", pwzName, pwzFile);
1069 break;
1070 }
1071 break;
1072 }
1073 }
1074
1075LExit:
1076 ReleaseStr(pwzCustomActionData);
1077 ReleaseStr(pwzName);
1078 ReleaseStr(pwzRemoteAddresses);
1079 ReleaseStr(pwzFile);
1080 ReleaseStr(pwzPort);
1081 ReleaseStr(pwzDescription);
1082 ::CoUninitialize();
1083
1084 return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILURE : ERROR_SUCCESS);
1085}
diff --git a/src/ext/Firewall/ca/fwca.def b/src/ext/Firewall/ca/fwca.def
new file mode 100644
index 00000000..d32c5379
--- /dev/null
+++ b/src/ext/Firewall/ca/fwca.def
@@ -0,0 +1,9 @@
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
4LIBRARY "fwca"
5
6EXPORTS
7 SchedFirewallExceptionsInstall
8 SchedFirewallExceptionsUninstall
9 ExecFirewallExceptions
diff --git a/src/ext/Firewall/ca/fwca.v3.ncrunchproject b/src/ext/Firewall/ca/fwca.v3.ncrunchproject
new file mode 100644
index 00000000..319cd523
--- /dev/null
+++ b/src/ext/Firewall/ca/fwca.v3.ncrunchproject
@@ -0,0 +1,5 @@
1<ProjectConfiguration>
2 <Settings>
3 <IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
4 </Settings>
5</ProjectConfiguration> \ No newline at end of file
diff --git a/src/ext/Firewall/ca/fwca.vcxproj b/src/ext/Firewall/ca/fwca.vcxproj
new file mode 100644
index 00000000..5e9a1db6
--- /dev/null
+++ b/src/ext/Firewall/ca/fwca.vcxproj
@@ -0,0 +1,81 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
5 <Import Project="..\..\packages\WixToolset.DUtil.4.0.56\build\WixToolset.DUtil.props" Condition="Exists('..\..\packages\WixToolset.DUtil.4.0.56\build\WixToolset.DUtil.props')" />
6 <Import Project="..\..\packages\WixToolset.WcaUtil.4.0.17\build\WixToolset.WcaUtil.props" Condition="Exists('..\..\packages\WixToolset.WcaUtil.4.0.17\build\WixToolset.WcaUtil.props')" />
7
8 <ItemGroup Label="ProjectConfigurations">
9 <ProjectConfiguration Include="Debug|ARM64">
10 <Configuration>Debug</Configuration>
11 <Platform>ARM64</Platform>
12 </ProjectConfiguration>
13 <ProjectConfiguration Include="Release|ARM64">
14 <Configuration>Release</Configuration>
15 <Platform>ARM64</Platform>
16 </ProjectConfiguration>
17
18 <ProjectConfiguration Include="Debug|X64">
19 <Configuration>Debug</Configuration>
20 <Platform>X64</Platform>
21 </ProjectConfiguration>
22 <ProjectConfiguration Include="Release|X64">
23 <Configuration>Release</Configuration>
24 <Platform>X64</Platform>
25 </ProjectConfiguration>
26
27 <ProjectConfiguration Include="Debug|Win32">
28 <Configuration>Debug</Configuration>
29 <Platform>Win32</Platform>
30 </ProjectConfiguration>
31 <ProjectConfiguration Include="Release|Win32">
32 <Configuration>Release</Configuration>
33 <Platform>Win32</Platform>
34 </ProjectConfiguration>
35 </ItemGroup>
36
37 <PropertyGroup Label="Globals">
38 <ProjectGuid>{F72D34CA-48DA-4DFD-91A9-A0C78BEF6981}</ProjectGuid>
39 <ConfigurationType>DynamicLibrary</ConfigurationType>
40 <TargetName>fwca</TargetName>
41 <PlatformToolset>v142</PlatformToolset>
42 <CharacterSet>Unicode</CharacterSet>
43 <ProjectModuleDefinitionFile>fwca.def</ProjectModuleDefinitionFile>
44 <Description>WiX Toolset Firewall CustomAction</Description>
45 </PropertyGroup>
46
47 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
48 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
49
50 <PropertyGroup>
51 <ProjectAdditionalLinkLibraries>msi.lib</ProjectAdditionalLinkLibraries>
52 </PropertyGroup>
53
54 <ItemGroup>
55 <ClCompile Include="dllmain.cpp">
56 <PrecompiledHeader>Create</PrecompiledHeader>
57 </ClCompile>
58 <ClCompile Include="firewall.cpp" />
59 </ItemGroup>
60
61 <ItemGroup>
62 <ClInclude Include="cost.h" />
63 <ClInclude Include="CustomMsiErrors.h" />
64 <ClInclude Include="precomp.h" />
65 </ItemGroup>
66
67 <ItemGroup>
68 <None Include="fwca.def" />
69 <None Include="packages.config" />
70 </ItemGroup>
71
72 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
73
74 <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
75 <PropertyGroup>
76 <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>
77 </PropertyGroup>
78 <Error Condition="!Exists('..\..\packages\WixToolset.DUtil.4.0.56\build\WixToolset.DUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\WixToolset.DUtil.4.0.56\build\WixToolset.DUtil.props'))" />
79 <Error Condition="!Exists('..\..\packages\WixToolset.WcaUtil.4.0.17\build\WixToolset.WcaUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\WixToolset.WcaUtil.4.0.17\build\WixToolset.WcaUtil.props'))" />
80 </Target>
81</Project>
diff --git a/src/ext/Firewall/ca/packages.config b/src/ext/Firewall/ca/packages.config
new file mode 100644
index 00000000..9d88f529
--- /dev/null
+++ b/src/ext/Firewall/ca/packages.config
@@ -0,0 +1,5 @@
1<?xml version="1.0" encoding="utf-8"?>
2<packages>
3 <package id="WixToolset.DUtil" version="4.0.56" targetFramework="native" />
4 <package id="WixToolset.WcaUtil" version="4.0.17" targetFramework="native" />
5</packages> \ No newline at end of file
diff --git a/src/ext/Firewall/ca/precomp.h b/src/ext/Firewall/ca/precomp.h
new file mode 100644
index 00000000..03845e1e
--- /dev/null
+++ b/src/ext/Firewall/ca/precomp.h
@@ -0,0 +1,19 @@
1#pragma once
2// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
3
4
5#include <windows.h>
6#include <msidefs.h>
7#include <msiquery.h>
8#include <strsafe.h>
9#include <netfw.h>
10
11#include "wcautil.h"
12#include "fileutil.h"
13#include "pathutil.h"
14#include "strutil.h"
15
16#include "CustomMsiErrors.h"
17#include "cost.h"
18
19#include "caDecor.h"
diff --git a/src/ext/Firewall/nuget.config b/src/ext/Firewall/nuget.config
new file mode 100644
index 00000000..aaf36562
--- /dev/null
+++ b/src/ext/Firewall/nuget.config
@@ -0,0 +1,18 @@
1<?xml version="1.0" encoding="utf-8"?>
2<configuration>
3 <packageSources>
4 <clear />
5 <add key="wixtoolset-burn" value="https://ci.appveyor.com/nuget/wixtoolset-burn" />
6 <add key="wixtoolset-data" value="https://ci.appveyor.com/nuget/wixtoolset-data" />
7 <add key="wixtoolset-extensibility" value="https://ci.appveyor.com/nuget/wixtoolset-extensibility" />
8 <add key="wixtoolset-core" value="https://ci.appveyor.com/nuget/wixtoolset-core" />
9 <add key="wixtoolset-core-native" value="https://ci.appveyor.com/nuget/wixtoolset-core-native" />
10 <add key="wixtoolset-burn" value="https://ci.appveyor.com/nuget/wixtoolset-burn" />
11 <add key="wixtoolset-dtf" value="https://ci.appveyor.com/nuget/wixtoolset-dtf" />
12 <add key="wixtoolset-dutil" value="https://ci.appveyor.com/nuget/wixtoolset-dutil" />
13 <add key="wixtoolset-wcautil" value="https://ci.appveyor.com/nuget/wixtoolset-wcautil" />
14 <add key="wixtoolset-tools" value="https://ci.appveyor.com/nuget/wixtoolset-tools" />
15 <add key="wixbuildtools" value="https://ci.appveyor.com/nuget/wixbuildtools" />
16 <add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
17 </packageSources>
18</configuration> \ No newline at end of file
diff --git a/src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs b/src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs
new file mode 100644
index 00000000..ffdc1326
--- /dev/null
+++ b/src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs
@@ -0,0 +1,80 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolsetTest.Firewall
4{
5 using System.Linq;
6 using WixBuildTools.TestSupport;
7 using WixToolset.Core.TestPackage;
8 using WixToolset.Firewall;
9 using Xunit;
10
11 public class FirewallExtensionFixture
12 {
13 [Fact]
14 public void CanBuildUsingFirewall()
15 {
16 var folder = TestData.Get(@"TestData\UsingFirewall");
17 var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder });
18
19 var results = build.BuildAndQuery(Build, "Wix4FirewallException", "CustomAction");
20 Assert.Equal(new[]
21 {
22 "CustomAction:Wix4ExecFirewallExceptionsInstall_X86\t3073\tWix4FWCA_X86\tExecFirewallExceptions\t",
23 "CustomAction:Wix4ExecFirewallExceptionsUninstall_X86\t3073\tWix4FWCA_X86\tExecFirewallExceptions\t",
24 "CustomAction:Wix4RollbackFirewallExceptionsInstall_X86\t3329\tWix4FWCA_X86\tExecFirewallExceptions\t",
25 "CustomAction:Wix4RollbackFirewallExceptionsUninstall_X86\t3329\tWix4FWCA_X86\tExecFirewallExceptions\t",
26 "CustomAction:Wix4SchedFirewallExceptionsInstall_X86\t1\tWix4FWCA_X86\tSchedFirewallExceptionsInstall\t",
27 "CustomAction:Wix4SchedFirewallExceptionsUninstall_X86\t1\tWix4FWCA_X86\tSchedFirewallExceptionsUninstall\t",
28 "Wix4FirewallException:ExampleFirewall\texample\t*\t42\t6\t\t0\t2147483647\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\tAn example firewall\t1",
29 }, results);
30 }
31
32 [Fact]
33 public void CanBuildUsingFirewallARM64()
34 {
35 var folder = TestData.Get(@"TestData\UsingFirewall");
36 var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder });
37
38 var results = build.BuildAndQuery(BuildARM64, "Wix4FirewallException", "CustomAction");
39 Assert.Equal(new[]
40 {
41 "CustomAction:Wix4ExecFirewallExceptionsInstall_A64\t3073\tWix4FWCA_A64\tExecFirewallExceptions\t",
42 "CustomAction:Wix4ExecFirewallExceptionsUninstall_A64\t3073\tWix4FWCA_A64\tExecFirewallExceptions\t",
43 "CustomAction:Wix4RollbackFirewallExceptionsInstall_A64\t3329\tWix4FWCA_A64\tExecFirewallExceptions\t",
44 "CustomAction:Wix4RollbackFirewallExceptionsUninstall_A64\t3329\tWix4FWCA_A64\tExecFirewallExceptions\t",
45 "CustomAction:Wix4SchedFirewallExceptionsInstall_A64\t1\tWix4FWCA_A64\tSchedFirewallExceptionsInstall\t",
46 "CustomAction:Wix4SchedFirewallExceptionsUninstall_A64\t1\tWix4FWCA_A64\tSchedFirewallExceptionsUninstall\t",
47 "Wix4FirewallException: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, "Wix4FirewallException");
58 Assert.Equal(new[]
59 {
60 "Wix4FirewallException:fex.5c8b_4C0THcQTvn8tpwhoRrgck\texample\t*\t42\t6\t\t0\t2147483647\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\tAn example outbound firewall\t2",
61 }, results);
62 }
63
64 private static void Build(string[] args)
65 {
66 var result = WixRunner.Execute(args);
67 result.AssertSuccess();
68 }
69
70 private static void BuildARM64(string[] args)
71 {
72 var newArgs = args.ToList();
73 newArgs.Add("-platform");
74 newArgs.Add("arm64");
75
76 var result = WixRunner.Execute(newArgs.ToArray());
77 result.AssertSuccess();
78 }
79 }
80}
diff --git a/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/Package.en-us.wxl b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/Package.en-us.wxl
new file mode 100644
index 00000000..38c12ac1
--- /dev/null
+++ b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/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/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/Package.wxs b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/Package.wxs
new file mode 100644
index 00000000..411893bc
--- /dev/null
+++ b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/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="047730a5-30fe-4a62-a520-da9381b8226a">
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/UsingFirewall/PackageComponents.wxs b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/PackageComponents.wxs
new file mode 100644
index 00000000..53e75427
--- /dev/null
+++ b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/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 Id="ExampleFirewall" Description="An example firewall" Name="example" Port="42">
9 <fw:RemoteAddress Value="*" />
10 </fw:FirewallException>
11 </Component>
12 </ComponentGroup>
13 </Fragment>
14</Wix>
diff --git a/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/example.txt b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/example.txt
new file mode 100644
index 00000000..1b4ffe8a
--- /dev/null
+++ b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/example.txt
@@ -0,0 +1 @@
This is example.txt. \ No newline at end of file
diff --git a/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/Package.en-us.wxl b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/Package.en-us.wxl
new file mode 100644
index 00000000..38c12ac1
--- /dev/null
+++ b/src/ext/Firewall/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/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/Package.wxs b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/Package.wxs
new file mode 100644
index 00000000..411893bc
--- /dev/null
+++ b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/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="047730a5-30fe-4a62-a520-da9381b8226a">
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/UsingOutboundFirewall/PackageComponents.wxs b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/PackageComponents.wxs
new file mode 100644
index 00000000..8084706e
--- /dev/null
+++ b/src/ext/Firewall/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 Value="*" />
10 </fw:FirewallException>
11 </Component>
12 </ComponentGroup>
13 </Fragment>
14</Wix>
diff --git a/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/example.txt b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/example.txt
new file mode 100644
index 00000000..1b4ffe8a
--- /dev/null
+++ b/src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/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
new file mode 100644
index 00000000..d04368c1
--- /dev/null
+++ b/src/ext/Firewall/test/WixToolsetTest.Firewall/WixToolsetTest.Firewall.csproj
@@ -0,0 +1,45 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4<Project Sdk="Microsoft.NET.Sdk">
5 <PropertyGroup>
6 <TargetFramework>netcoreapp3.1</TargetFramework>
7 <IsPackable>false</IsPackable>
8 </PropertyGroup>
9
10 <PropertyGroup>
11 <NoWarn>NU1701</NoWarn>
12 </PropertyGroup>
13
14 <ItemGroup>
15 <Content Include="TestData\UsingFirewall\example.txt" CopyToOutputDirectory="PreserveNewest" />
16 <Content Include="TestData\UsingFirewall\Package.en-us.wxl" CopyToOutputDirectory="PreserveNewest" />
17 <Content Include="TestData\UsingFirewall\Package.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" />
23 </ItemGroup>
24
25 <ItemGroup>
26 <ProjectReference Include="..\..\wixext\WixToolset.Firewall.wixext.csproj" />
27 </ItemGroup>
28
29 <ItemGroup>
30 <PackageReference Include="WixToolset.Core" Version="4.0.*" />
31 <PackageReference Include="WixToolset.Core.Burn" Version="4.0.*" />
32 <PackageReference Include="WixToolset.Core.WindowsInstaller" Version="4.0.*" />
33 <PackageReference Include="WixToolset.Core.TestPackage" Version="4.0.*" />
34 </ItemGroup>
35
36 <ItemGroup>
37 <PackageReference Include="WixBuildTools.TestSupport" Version="4.0.*" />
38 </ItemGroup>
39
40 <ItemGroup>
41 <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" />
42 <PackageReference Include="xunit" Version="2.4.1" />
43 <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" PrivateAssets="All" />
44 </ItemGroup>
45</Project>
diff --git a/src/ext/Firewall/test/WixToolsetTest.Firewall/WixToolsetTest.Firewall.v3.ncrunchproject b/src/ext/Firewall/test/WixToolsetTest.Firewall/WixToolsetTest.Firewall.v3.ncrunchproject
new file mode 100644
index 00000000..7b5b2139
--- /dev/null
+++ b/src/ext/Firewall/test/WixToolsetTest.Firewall/WixToolsetTest.Firewall.v3.ncrunchproject
@@ -0,0 +1,5 @@
1<ProjectConfiguration>
2 <Settings>
3 <CopyReferencedAssembliesToWorkspace>True</CopyReferencedAssembliesToWorkspace>
4 </Settings>
5</ProjectConfiguration> \ No newline at end of file
diff --git a/src/ext/Firewall/wix.snk b/src/ext/Firewall/wix.snk
new file mode 100644
index 00000000..3908a66a
--- /dev/null
+++ b/src/ext/Firewall/wix.snk
Binary files differ
diff --git a/src/ext/Firewall/wixext/FirewallCompiler.cs b/src/ext/Firewall/wixext/FirewallCompiler.cs
new file mode 100644
index 00000000..cbe82d37
--- /dev/null
+++ b/src/ext/Firewall/wixext/FirewallCompiler.cs
@@ -0,0 +1,354 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.Firewall
4{
5 using System;
6 using System.Collections.Generic;
7 using System.Xml.Linq;
8 using WixToolset.Data;
9 using WixToolset.Extensibility;
10 using WixToolset.Extensibility.Data;
11 using WixToolset.Firewall.Symbols;
12
13 /// <summary>
14 /// The compiler for the WiX Toolset Firewall Extension.
15 /// </summary>
16 public sealed class FirewallCompiler : BaseCompilerExtension
17 {
18 public override XNamespace Namespace => "http://wixtoolset.org/schemas/v4/wxs/firewall";
19
20 /// <summary>
21 /// Processes an element for the Compiler.
22 /// </summary>
23 /// <param name="sourceLineNumbers">Source line number for the parent element.</param>
24 /// <param name="parentElement">Parent element of element to process.</param>
25 /// <param name="element">Element to process.</param>
26 /// <param name="contextValues">Extra information about the context in which this element is being parsed.</param>
27 public override void ParseElement(Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, IDictionary<string, string> context)
28 {
29 switch (parentElement.Name.LocalName)
30 {
31 case "File":
32 var fileId = context["FileId"];
33 var fileComponentId = context["ComponentId"];
34
35 switch (element.Name.LocalName)
36 {
37 case "FirewallException":
38 this.ParseFirewallExceptionElement(intermediate, section, element, fileComponentId, fileId);
39 break;
40 default:
41 this.ParseHelper.UnexpectedElement(parentElement, element);
42 break;
43 }
44 break;
45 case "Component":
46 var componentId = context["ComponentId"];
47
48 switch (element.Name.LocalName)
49 {
50 case "FirewallException":
51 this.ParseFirewallExceptionElement(intermediate, section, element, componentId, null);
52 break;
53 default:
54 this.ParseHelper.UnexpectedElement(parentElement, element);
55 break;
56 }
57 break;
58 default:
59 this.ParseHelper.UnexpectedElement(parentElement, element);
60 break;
61 }
62 }
63
64 /// <summary>
65 /// Parses a FirewallException element.
66 /// </summary>
67 /// <param name="element">The element to parse.</param>
68 /// <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>
70 private void ParseFirewallExceptionElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string fileId)
71 {
72 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
73 Identifier id = null;
74 string name = null;
75 int attributes = 0;
76 string file = null;
77 string program = null;
78 string port = null;
79 int? protocol = null;
80 int? profile = null;
81 string scope = null;
82 string remoteAddresses = null;
83 string description = null;
84 int? direction = null;
85
86 foreach (var attrib in element.Attributes())
87 {
88 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
89 {
90 switch (attrib.Name.LocalName)
91 {
92 case "Id":
93 id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib);
94 break;
95 case "Name":
96 name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
97 break;
98 case "File":
99 if (null != fileId)
100 {
101 this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, "File", "File"));
102 }
103 else
104 {
105 file = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
106 }
107 break;
108 case "IgnoreFailure":
109 if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib))
110 {
111 attributes |= 0x1; // feaIgnoreFailures
112 }
113 break;
114 case "Program":
115 if (null != fileId)
116 {
117 this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, "Program", "File"));
118 }
119 else
120 {
121 program = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
122 }
123 break;
124 case "Port":
125 port = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
126 break;
127 case "Protocol":
128 var protocolValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
129 switch (protocolValue)
130 {
131 case "tcp":
132 protocol = FirewallConstants.NET_FW_IP_PROTOCOL_TCP;
133 break;
134 case "udp":
135 protocol = FirewallConstants.NET_FW_IP_PROTOCOL_UDP;
136 break;
137 default:
138 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Protocol", protocolValue, "tcp", "udp"));
139 break;
140 }
141 break;
142 case "Scope":
143 scope = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
144 switch (scope)
145 {
146 case "any":
147 remoteAddresses = "*";
148 break;
149 case "localSubnet":
150 remoteAddresses = "LocalSubnet";
151 break;
152 default:
153 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Scope", scope, "any", "localSubnet"));
154 break;
155 }
156 break;
157 case "Profile":
158 var profileValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
159 switch (profileValue)
160 {
161 case "domain":
162 profile = FirewallConstants.NET_FW_PROFILE2_DOMAIN;
163 break;
164 case "private":
165 profile = FirewallConstants.NET_FW_PROFILE2_PRIVATE;
166 break;
167 case "public":
168 profile = FirewallConstants.NET_FW_PROFILE2_PUBLIC;
169 break;
170 case "all":
171 profile = FirewallConstants.NET_FW_PROFILE2_ALL;
172 break;
173 default:
174 this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Profile", profileValue, "domain", "private", "public", "all"));
175 break;
176 }
177 break;
178 case "Description":
179 description = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
180 break;
181 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;
186 default:
187 this.ParseHelper.UnexpectedAttribute(element, attrib);
188 break;
189 }
190 }
191 else
192 {
193 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
194 }
195 }
196
197 // parse RemoteAddress children
198 foreach (var child in element.Elements())
199 {
200 if (this.Namespace == child.Name.Namespace)
201 {
202 switch (child.Name.LocalName)
203 {
204 case "RemoteAddress":
205 if (null != scope)
206 {
207 this.Messaging.Write(FirewallErrors.IllegalRemoteAddressWithScopeAttribute(sourceLineNumbers));
208 }
209 else
210 {
211 this.ParseRemoteAddressElement(intermediate, section, child, ref remoteAddresses);
212 }
213 break;
214 default:
215 this.ParseHelper.UnexpectedElement(element, child);
216 break;
217 }
218 }
219 else
220 {
221 this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child);
222 }
223 }
224
225 if (null == id)
226 {
227 id = this.ParseHelper.CreateIdentifier("fex", name, remoteAddresses, componentId);
228 }
229
230 // Name is required
231 if (null == name)
232 {
233 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name"));
234 }
235
236 // Scope or child RemoteAddress(es) are required
237 if (null == remoteAddresses)
238 {
239 this.Messaging.Write(ErrorMessages.ExpectedAttributeOrElement(sourceLineNumbers, element.Name.LocalName, "Scope", "RemoteAddress"));
240 }
241
242 // can't have both Program and File
243 if (null != program && null != file)
244 {
245 this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "File", "Program"));
246 }
247
248 // must be nested under File, have File or Program attributes, or have Port attribute
249 if (String.IsNullOrEmpty(fileId) && String.IsNullOrEmpty(file) && String.IsNullOrEmpty(program) && String.IsNullOrEmpty(port))
250 {
251 this.Messaging.Write(FirewallErrors.NoExceptionSpecified(sourceLineNumbers));
252 }
253
254 if (!this.Messaging.EncounteredError)
255 {
256 // at this point, File attribute and File parent element are treated the same
257 if (null != file)
258 {
259 fileId = file;
260 }
261
262 var symbol = section.AddSymbol(new WixFirewallExceptionSymbol(sourceLineNumbers, id)
263 {
264 Name = name,
265 RemoteAddresses = remoteAddresses,
266 Profile = profile ?? FirewallConstants.NET_FW_PROFILE2_ALL,
267 ComponentRef = componentId,
268 Description = description,
269 Direction = direction ?? FirewallConstants.NET_FW_RULE_DIR_IN,
270 });
271
272 if (!String.IsNullOrEmpty(port))
273 {
274 symbol.Port = port;
275
276 if (!protocol.HasValue)
277 {
278 // default protocol is "TCP"
279 protocol = FirewallConstants.NET_FW_IP_PROTOCOL_TCP;
280 }
281 }
282
283 if (protocol.HasValue)
284 {
285 symbol.Protocol = protocol.Value;
286 }
287
288 if (!String.IsNullOrEmpty(fileId))
289 {
290 symbol.Program = $"[#{fileId}]";
291 this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.File, fileId);
292 }
293 else if (!String.IsNullOrEmpty(program))
294 {
295 symbol.Program = program;
296 }
297
298 if (CompilerConstants.IntegerNotSet != attributes)
299 {
300 symbol.Attributes = attributes;
301 }
302
303 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedFirewallExceptionsInstall", this.Context.Platform, CustomActionPlatforms.ARM64 | CustomActionPlatforms.X64 | CustomActionPlatforms.X86);
304 this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedFirewallExceptionsUninstall", this.Context.Platform, CustomActionPlatforms.ARM64 | CustomActionPlatforms.X64 | CustomActionPlatforms.X86);
305 }
306 }
307
308 /// <summary>
309 /// Parses a RemoteAddress element
310 /// </summary>
311 /// <param name="element">The element to parse.</param>
312 private void ParseRemoteAddressElement(Intermediate intermediate, IntermediateSection section, XElement element, ref string remoteAddresses)
313 {
314 var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element);
315 string address = null;
316
317 // no attributes
318 foreach (var attrib in element.Attributes())
319 {
320 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace)
321 {
322 switch (attrib.Name.LocalName)
323 {
324 case "Value":
325 address = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib);
326 break;
327 }
328 }
329 else
330 {
331 this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib);
332 }
333 }
334
335 this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element);
336
337 if (String.IsNullOrEmpty(address))
338 {
339 this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Value"));
340 }
341 else
342 {
343 if (String.IsNullOrEmpty(remoteAddresses))
344 {
345 remoteAddresses = address;
346 }
347 else
348 {
349 remoteAddresses = String.Concat(remoteAddresses, ",", address);
350 }
351 }
352 }
353 }
354}
diff --git a/src/ext/Firewall/wixext/FirewallConstants.cs b/src/ext/Firewall/wixext/FirewallConstants.cs
new file mode 100644
index 00000000..7bb12ba4
--- /dev/null
+++ b/src/ext/Firewall/wixext/FirewallConstants.cs
@@ -0,0 +1,23 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.Firewall
4{
5 using System;
6 using System.Collections.Generic;
7 using System.Text;
8
9 static class FirewallConstants
10 {
11 // from icftypes.h
12 public const int NET_FW_RULE_DIR_IN = 1;
13 public const int NET_FW_RULE_DIR_OUT = 2;
14 public const int NET_FW_IP_PROTOCOL_TCP = 6;
15 public const int NET_FW_IP_PROTOCOL_UDP = 17;
16
17 // from icftypes.h
18 public const int NET_FW_PROFILE2_DOMAIN = 0x0001;
19 public const int NET_FW_PROFILE2_PRIVATE = 0x0002;
20 public const int NET_FW_PROFILE2_PUBLIC = 0x0004;
21 public const int NET_FW_PROFILE2_ALL = 0x7FFFFFFF;
22 }
23}
diff --git a/src/ext/Firewall/wixext/FirewallDecompiler.cs b/src/ext/Firewall/wixext/FirewallDecompiler.cs
new file mode 100644
index 00000000..c9478de1
--- /dev/null
+++ b/src/ext/Firewall/wixext/FirewallDecompiler.cs
@@ -0,0 +1,182 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.Firewall
4{
5#if TODO_CONSIDER_DECOMPILER
6 using System;
7 using System.Collections;
8 using System.Diagnostics;
9 using System.Globalization;
10 using WixToolset.Data;
11 using WixToolset.Extensibility;
12 using Firewall = WixToolset.Extensions.Serialize.Firewall;
13 using Wix = WixToolset.Data.Serialize;
14
15 /// <summary>
16 /// The decompiler for the WiX Toolset Firewall Extension.
17 /// </summary>
18 public sealed class FirewallDecompiler : DecompilerExtension
19 {
20 /// <summary>
21 /// Creates a decompiler for Firewall Extension.
22 /// </summary>
23 public FirewallDecompiler()
24 {
25 this.TableDefinitions = FirewallExtensionData.GetExtensionTableDefinitions();
26 }
27
28 /// <summary>
29 /// Get the extensions library to be removed.
30 /// </summary>
31 /// <param name="tableDefinitions">Table definitions for library.</param>
32 /// <returns>Library to remove from decompiled output.</returns>
33 public override Library GetLibraryToRemove(TableDefinitionCollection tableDefinitions)
34 {
35 return FirewallExtensionData.GetExtensionLibrary(tableDefinitions);
36 }
37
38 /// <summary>
39 /// Decompiles an extension table.
40 /// </summary>
41 /// <param name="table">The table to decompile.</param>
42 public override void DecompileTable(Table table)
43 {
44 switch (table.Name)
45 {
46 case "WixFirewallException":
47 this.DecompileWixFirewallExceptionTable(table);
48 break;
49 default:
50 base.DecompileTable(table);
51 break;
52 }
53 }
54
55 /// <summary>
56 /// Decompile the WixFirewallException table.
57 /// </summary>
58 /// <param name="table">The table to decompile.</param>
59 private void DecompileWixFirewallExceptionTable(Table table)
60 {
61 foreach (Row row in table.Rows)
62 {
63 Firewall.FirewallException fire = new Firewall.FirewallException();
64 fire.Id = (string)row[0];
65 fire.Name = (string)row[1];
66
67 string[] addresses = ((string)row[2]).Split(',');
68 if (1 == addresses.Length)
69 {
70 // special-case the Scope attribute values
71 if ("*" == addresses[0])
72 {
73 fire.Scope = Firewall.FirewallException.ScopeType.any;
74 }
75 else if ("LocalSubnet" == addresses[0])
76 {
77 fire.Scope = Firewall.FirewallException.ScopeType.localSubnet;
78 }
79 else
80 {
81 FirewallDecompiler.AddRemoteAddress(fire, addresses[0]);
82 }
83 }
84 else
85 {
86 foreach (string address in addresses)
87 {
88 FirewallDecompiler.AddRemoteAddress(fire, address);
89 }
90 }
91
92 if (!row.IsColumnEmpty(3))
93 {
94 fire.Port = (string)row[3];
95 }
96
97 if (!row.IsColumnEmpty(4))
98 {
99 switch (Convert.ToInt32(row[4]))
100 {
101 case FirewallConstants.NET_FW_IP_PROTOCOL_TCP:
102 fire.Protocol = Firewall.FirewallException.ProtocolType.tcp;
103 break;
104 case FirewallConstants.NET_FW_IP_PROTOCOL_UDP:
105 fire.Protocol = Firewall.FirewallException.ProtocolType.udp;
106 break;
107 }
108 }
109
110 if (!row.IsColumnEmpty(5))
111 {
112 fire.Program = (string)row[5];
113 }
114
115 if (!row.IsColumnEmpty(6))
116 {
117 int attr = Convert.ToInt32(row[6]);
118 if (0x1 == (attr & 0x1)) // feaIgnoreFailures
119 {
120 fire.IgnoreFailure = Firewall.YesNoType.yes;
121 }
122 }
123
124 if (!row.IsColumnEmpty(7))
125 {
126 switch (Convert.ToInt32(row[7]))
127 {
128 case FirewallConstants.NET_FW_PROFILE2_DOMAIN:
129 fire.Profile = Firewall.FirewallException.ProfileType.domain;
130 break;
131 case FirewallConstants.NET_FW_PROFILE2_PRIVATE:
132 fire.Profile = Firewall.FirewallException.ProfileType.@private;
133 break;
134 case FirewallConstants.NET_FW_PROFILE2_PUBLIC:
135 fire.Profile = Firewall.FirewallException.ProfileType.@public;
136 break;
137 case FirewallConstants.NET_FW_PROFILE2_ALL:
138 fire.Profile = Firewall.FirewallException.ProfileType.all;
139 break;
140 }
141 }
142
143 // Description column is new in v3.6
144 if (9 < row.Fields.Length && !row.IsColumnEmpty(9))
145 {
146 fire.Description = (string)row[9];
147 }
148
149 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
162 Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[8]);
163 if (null != component)
164 {
165 component.AddChild(fire);
166 }
167 else
168 {
169 this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[6], "Component"));
170 }
171 }
172 }
173
174 private static void AddRemoteAddress(Firewall.FirewallException fire, string address)
175 {
176 Firewall.RemoteAddress remote = new Firewall.RemoteAddress();
177 remote.Content = address;
178 fire.AddChild(remote);
179 }
180 }
181#endif
182}
diff --git a/src/ext/Firewall/wixext/FirewallErrors.cs b/src/ext/Firewall/wixext/FirewallErrors.cs
new file mode 100644
index 00000000..b2dac782
--- /dev/null
+++ b/src/ext/Firewall/wixext/FirewallErrors.cs
@@ -0,0 +1,36 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.Firewall
4{
5 using System.Resources;
6 using WixToolset.Data;
7
8 public static class FirewallErrors
9 {
10 public static Message IllegalRemoteAddressWithScopeAttribute(SourceLineNumber sourceLineNumbers)
11 {
12 return Message(sourceLineNumbers, Ids.IllegalRemoteAddressWithScopeAttribute, "The RemoteAddress element cannot be specified because its parent FirewallException already specified the Scope attribute. To use RemoteAddress elements, omit the Scope attribute.");
13 }
14
15 public static Message 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)
21 {
22 return new Message(sourceLineNumber, MessageLevel.Error, (int)id, format, args);
23 }
24
25 private static Message Message(SourceLineNumber sourceLineNumber, Ids id, ResourceManager resourceManager, string resourceName, params object[] args)
26 {
27 return new Message(sourceLineNumber, MessageLevel.Error, (int)id, resourceManager, resourceName, args);
28 }
29
30 public enum Ids
31 {
32 IllegalRemoteAddressWithScopeAttribute = 6401,
33 NoExceptionSpecified = 6403,
34 }
35 }
36}
diff --git a/src/ext/Firewall/wixext/FirewallExtensionData.cs b/src/ext/Firewall/wixext/FirewallExtensionData.cs
new file mode 100644
index 00000000..7481d993
--- /dev/null
+++ b/src/ext/Firewall/wixext/FirewallExtensionData.cs
@@ -0,0 +1,23 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.Firewall
4{
5 using WixToolset.Data;
6 using WixToolset.Extensibility;
7
8 public sealed class FirewallExtensionData : BaseExtensionData
9 {
10 public override string DefaultCulture => "en-US";
11
12 public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition)
13 {
14 symbolDefinition = FirewallSymbolDefinitions.ByName(name);
15 return symbolDefinition != null;
16 }
17
18 public override Intermediate GetLibrary(ISymbolDefinitionCreator symbolDefinitions)
19 {
20 return Intermediate.Load(typeof(FirewallExtensionData).Assembly, "WixToolset.Firewall.firewall.wixlib", symbolDefinitions);
21 }
22 }
23}
diff --git a/src/ext/Firewall/wixext/FirewallExtensionFactory.cs b/src/ext/Firewall/wixext/FirewallExtensionFactory.cs
new file mode 100644
index 00000000..279b322a
--- /dev/null
+++ b/src/ext/Firewall/wixext/FirewallExtensionFactory.cs
@@ -0,0 +1,18 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.Firewall
4{
5 using System;
6 using System.Collections.Generic;
7 using WixToolset.Extensibility;
8
9 public class FirewallExtensionFactory : BaseExtensionFactory
10 {
11 protected override IReadOnlyCollection<Type> ExtensionTypes => new[]
12 {
13 typeof(FirewallCompiler),
14 typeof(FirewallExtensionData),
15 typeof(FirewallWindowsInstallerBackendBinderExtension),
16 };
17 }
18}
diff --git a/src/ext/Firewall/wixext/FirewallTableDefinitions.cs b/src/ext/Firewall/wixext/FirewallTableDefinitions.cs
new file mode 100644
index 00000000..04918f5f
--- /dev/null
+++ b/src/ext/Firewall/wixext/FirewallTableDefinitions.cs
@@ -0,0 +1,34 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.Firewall
4{
5 using WixToolset.Data.WindowsInstaller;
6
7 public static class FirewallTableDefinitions
8 {
9 public static readonly TableDefinition WixFirewallException = new TableDefinition(
10 "Wix4FirewallException",
11 FirewallSymbolDefinitions.WixFirewallException,
12 new[]
13 {
14 new ColumnDefinition("Wix4FirewallException", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "The primary key, a non-localized token.", modularizeType: ColumnModularizeType.Column),
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),
17 new ColumnDefinition("Port", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, minValue: 1, description: "Port number.", modularizeType: ColumnModularizeType.Property),
18 new ColumnDefinition("Protocol", ColumnType.Number, 1, primaryKey: false, nullable: true, ColumnCategory.Integer, minValue: 6, maxValue: 17, description: "Protocol (6=TCP; 17=UDP)."),
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"),
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),
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)"),
25 },
26 symbolIdIsPrimaryKey: true
27 );
28
29 public static readonly TableDefinition[] All = new[]
30 {
31 WixFirewallException,
32 };
33 }
34}
diff --git a/src/ext/Firewall/wixext/FirewallWindowsInstallerBackendExtension.cs b/src/ext/Firewall/wixext/FirewallWindowsInstallerBackendExtension.cs
new file mode 100644
index 00000000..b5b97d85
--- /dev/null
+++ b/src/ext/Firewall/wixext/FirewallWindowsInstallerBackendExtension.cs
@@ -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
3namespace WixToolset.Firewall
4{
5 using System.Collections.Generic;
6 using WixToolset.Data.WindowsInstaller;
7 using WixToolset.Extensibility;
8
9 public class FirewallWindowsInstallerBackendBinderExtension : BaseWindowsInstallerBackendBinderExtension
10 {
11 public override IReadOnlyCollection<TableDefinition> TableDefinitions => FirewallTableDefinitions.All;
12 }
13}
diff --git a/src/ext/Firewall/wixext/Symbols/FirewallSymbolDefinitions.cs b/src/ext/Firewall/wixext/Symbols/FirewallSymbolDefinitions.cs
new file mode 100644
index 00000000..887893c7
--- /dev/null
+++ b/src/ext/Firewall/wixext/Symbols/FirewallSymbolDefinitions.cs
@@ -0,0 +1,39 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.Firewall
4{
5 using System;
6 using WixToolset.Data;
7
8 public enum FirewallSymbolDefinitionType
9 {
10 WixFirewallException,
11 }
12
13 public static partial class FirewallSymbolDefinitions
14 {
15 public static readonly Version Version = new Version("4.0.0");
16
17 public static IntermediateSymbolDefinition ByName(string name)
18 {
19 if (!Enum.TryParse(name, out FirewallSymbolDefinitionType type))
20 {
21 return null;
22 }
23
24 return ByType(type);
25 }
26
27 public static IntermediateSymbolDefinition ByType(FirewallSymbolDefinitionType type)
28 {
29 switch (type)
30 {
31 case FirewallSymbolDefinitionType.WixFirewallException:
32 return FirewallSymbolDefinitions.WixFirewallException;
33
34 default:
35 throw new ArgumentOutOfRangeException(nameof(type));
36 }
37 }
38 }
39}
diff --git a/src/ext/Firewall/wixext/Symbols/WixFirewallExceptionSymbol.cs b/src/ext/Firewall/wixext/Symbols/WixFirewallExceptionSymbol.cs
new file mode 100644
index 00000000..620de969
--- /dev/null
+++ b/src/ext/Firewall/wixext/Symbols/WixFirewallExceptionSymbol.cs
@@ -0,0 +1,119 @@
1// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
3namespace WixToolset.Firewall
4{
5 using WixToolset.Data;
6 using WixToolset.Firewall.Symbols;
7
8 public static partial class FirewallSymbolDefinitions
9 {
10 public static readonly IntermediateSymbolDefinition WixFirewallException = new IntermediateSymbolDefinition(
11 FirewallSymbolDefinitionType.WixFirewallException.ToString(),
12 new[]
13 {
14 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Name), IntermediateFieldType.String),
15 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.RemoteAddresses), IntermediateFieldType.String),
16 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Port), IntermediateFieldType.String),
17 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Protocol), IntermediateFieldType.Number),
18 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Program), IntermediateFieldType.String),
19 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Attributes), IntermediateFieldType.Number),
20 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Profile), IntermediateFieldType.Number),
21 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.ComponentRef), IntermediateFieldType.String),
22 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Description), IntermediateFieldType.String),
23 new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Direction), IntermediateFieldType.Number),
24 },
25 typeof(WixFirewallExceptionSymbol));
26 }
27}
28
29namespace WixToolset.Firewall.Symbols
30{
31 using WixToolset.Data;
32
33 public enum WixFirewallExceptionSymbolFields
34 {
35 Name,
36 RemoteAddresses,
37 Port,
38 Protocol,
39 Program,
40 Attributes,
41 Profile,
42 ComponentRef,
43 Description,
44 Direction,
45 }
46
47 public class WixFirewallExceptionSymbol : IntermediateSymbol
48 {
49 public WixFirewallExceptionSymbol() : base(FirewallSymbolDefinitions.WixFirewallException, null, null)
50 {
51 }
52
53 public WixFirewallExceptionSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(FirewallSymbolDefinitions.WixFirewallException, sourceLineNumber, id)
54 {
55 }
56
57 public IntermediateField this[WixFirewallExceptionSymbolFields index] => this.Fields[(int)index];
58
59 public string Name
60 {
61 get => this.Fields[(int)WixFirewallExceptionSymbolFields.Name].AsString();
62 set => this.Set((int)WixFirewallExceptionSymbolFields.Name, value);
63 }
64
65 public string RemoteAddresses
66 {
67 get => this.Fields[(int)WixFirewallExceptionSymbolFields.RemoteAddresses].AsString();
68 set => this.Set((int)WixFirewallExceptionSymbolFields.RemoteAddresses, value);
69 }
70
71 public string Port
72 {
73 get => this.Fields[(int)WixFirewallExceptionSymbolFields.Port].AsString();
74 set => this.Set((int)WixFirewallExceptionSymbolFields.Port, value);
75 }
76
77 public int? Protocol
78 {
79 get => this.Fields[(int)WixFirewallExceptionSymbolFields.Protocol].AsNullableNumber();
80 set => this.Set((int)WixFirewallExceptionSymbolFields.Protocol, value);
81 }
82
83 public string Program
84 {
85 get => this.Fields[(int)WixFirewallExceptionSymbolFields.Program].AsString();
86 set => this.Set((int)WixFirewallExceptionSymbolFields.Program, value);
87 }
88
89 public int Attributes
90 {
91 get => this.Fields[(int)WixFirewallExceptionSymbolFields.Attributes].AsNumber();
92 set => this.Set((int)WixFirewallExceptionSymbolFields.Attributes, value);
93 }
94
95 public int Profile
96 {
97 get => this.Fields[(int)WixFirewallExceptionSymbolFields.Profile].AsNumber();
98 set => this.Set((int)WixFirewallExceptionSymbolFields.Profile, value);
99 }
100
101 public string ComponentRef
102 {
103 get => this.Fields[(int)WixFirewallExceptionSymbolFields.ComponentRef].AsString();
104 set => this.Set((int)WixFirewallExceptionSymbolFields.ComponentRef, value);
105 }
106
107 public string Description
108 {
109 get => this.Fields[(int)WixFirewallExceptionSymbolFields.Description].AsString();
110 set => this.Set((int)WixFirewallExceptionSymbolFields.Description, value);
111 }
112
113 public int Direction
114 {
115 get => this.Fields[(int)WixFirewallExceptionSymbolFields.Direction].AsNumber();
116 set => this.Set((int)WixFirewallExceptionSymbolFields.Direction, value);
117 }
118 }
119} \ No newline at end of file
diff --git a/src/ext/Firewall/wixext/WixToolset.Firewall.wixext.csproj b/src/ext/Firewall/wixext/WixToolset.Firewall.wixext.csproj
new file mode 100644
index 00000000..6704dad2
--- /dev/null
+++ b/src/ext/Firewall/wixext/WixToolset.Firewall.wixext.csproj
@@ -0,0 +1,31 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4<Project Sdk="Microsoft.NET.Sdk">
5 <PropertyGroup>
6 <TargetFramework>netstandard2.0</TargetFramework>
7 <RootNamespace>WixToolset.Firewall</RootNamespace>
8 <Description>WiX Toolset Firewallity Extension</Description>
9 <Title>WiX Toolset Firewall Extension</Title>
10 <IsTool>true</IsTool>
11 <ContentTargetFolders>build</ContentTargetFolders>
12 </PropertyGroup>
13
14 <ItemGroup>
15 <Content Include="$(MSBuildThisFileName).targets" />
16 <EmbeddedResource Include="$(OutputPath)..\firewall.wixlib" />
17 </ItemGroup>
18
19 <ItemGroup>
20 <PackageReference Include="WixToolset.Data" Version="4.0.*" PrivateAssets="all" />
21 <PackageReference Include="WixToolset.Extensibility" Version="4.0.*" PrivateAssets="all" />
22 </ItemGroup>
23
24 <ItemGroup>
25 <ProjectReference Include="..\wixlib\firewall.wixproj" ReferenceOutputAssembly="false" Condition=" '$(NCrunch)'=='' " />
26 </ItemGroup>
27
28 <ItemGroup>
29 <PackageReference Include="Nerdbank.GitVersioning" Version="3.3.37" PrivateAssets="all" />
30 </ItemGroup>
31</Project>
diff --git a/src/ext/Firewall/wixext/WixToolset.Firewall.wixext.targets b/src/ext/Firewall/wixext/WixToolset.Firewall.wixext.targets
new file mode 100644
index 00000000..c717450f
--- /dev/null
+++ b/src/ext/Firewall/wixext/WixToolset.Firewall.wixext.targets
@@ -0,0 +1,11 @@
1<?xml version="1.0" encoding="utf-8"?>
2<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
3
4<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
5 <PropertyGroup>
6 <WixToolsetFirewallWixextPath Condition=" '$(WixToolsetFirewallWixextPath)' == '' ">$(MSBuildThisFileDirectory)..\tools\WixToolset.Firewall.wixext.dll</WixToolsetFirewallWixextPath>
7 </PropertyGroup>
8 <ItemGroup>
9 <WixExtension Include="$(WixToolsetFirewallWixextPath)" />
10 </ItemGroup>
11</Project>
diff --git a/src/ext/Firewall/wixlib/FirewallExtension.wxs b/src/ext/Firewall/wixlib/FirewallExtension.wxs
new file mode 100644
index 00000000..56ad693e
--- /dev/null
+++ b/src/ext/Firewall/wixlib/FirewallExtension.wxs
@@ -0,0 +1,11 @@
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">
5 <?include caerr.wxi ?>
6 <Fragment>
7 <UI Id="WixFirewallErrors">
8 <Error Id="$(var.msierrFirewallCannotConnect)" Message="!(loc.msierrFirewallCannotConnect)" />
9 </UI>
10 </Fragment>
11</Wix>
diff --git a/src/ext/Firewall/wixlib/FirewallExtension_Platform.wxi b/src/ext/Firewall/wixlib/FirewallExtension_Platform.wxi
new file mode 100644
index 00000000..3861bd5d
--- /dev/null
+++ b/src/ext/Firewall/wixlib/FirewallExtension_Platform.wxi
@@ -0,0 +1,36 @@
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<Include xmlns="http://wixtoolset.org/schemas/v4/wxs">
4 <?include caDecor.wxi ?>
5 <Fragment>
6 <UIRef Id="WixFirewallErrors" />
7 <UI>
8 <ProgressText Action="$(var.Prefix)SchedFirewallExceptionsInstall$(var.Suffix)" Message="!(loc.WixSchedFirewallExceptionsInstall)" />
9 <ProgressText Action="$(var.Prefix)SchedFirewallExceptionsUninstall$(var.Suffix)" Message="!(loc.WixSchedFirewallExceptionsUninstall)" />
10 <ProgressText Action="$(var.Prefix)RollbackFirewallExceptionsInstall$(var.Suffix)" Message="!(loc.WixRollbackFirewallExceptionsInstall)" />
11 <ProgressText Action="$(var.Prefix)ExecFirewallExceptionsInstall$(var.Suffix)" Message="!(loc.WixExecFirewallExceptionsInstall)" />
12 <ProgressText Action="$(var.Prefix)RollbackFirewallExceptionsUninstall$(var.Suffix)" Message="!(loc.WixRollbackFirewallExceptionsUninstall)" />
13 <ProgressText Action="$(var.Prefix)ExecFirewallExceptionsUninstall$(var.Suffix)" Message="!(loc.WixExecFirewallExceptionsUninstall)" />
14 </UI>
15
16 <CustomAction Id="$(var.Prefix)SchedFirewallExceptionsInstall$(var.Suffix)" DllEntry="SchedFirewallExceptionsInstall" Execute="immediate" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix)FWCA$(var.Suffix)" />
17 <CustomAction Id="$(var.Prefix)SchedFirewallExceptionsUninstall$(var.Suffix)" DllEntry="SchedFirewallExceptionsUninstall" Execute="immediate" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix)FWCA$(var.Suffix)" />
18 <CustomAction Id="$(var.Prefix)RollbackFirewallExceptionsInstall$(var.Suffix)" DllEntry="ExecFirewallExceptions" Execute="rollback" Impersonate="no" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix)FWCA$(var.Suffix)" />
19 <CustomAction Id="$(var.Prefix)ExecFirewallExceptionsInstall$(var.Suffix)" DllEntry="ExecFirewallExceptions" Execute="deferred" Impersonate="no" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix)FWCA$(var.Suffix)" />
20 <CustomAction Id="$(var.Prefix)RollbackFirewallExceptionsUninstall$(var.Suffix)" DllEntry="ExecFirewallExceptions" Execute="rollback" Impersonate="no" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix)FWCA$(var.Suffix)" />
21 <CustomAction Id="$(var.Prefix)ExecFirewallExceptionsUninstall$(var.Suffix)" DllEntry="ExecFirewallExceptions" Execute="deferred" Impersonate="no" Return="check" SuppressModularization="yes" BinaryRef="$(var.Prefix)FWCA$(var.Suffix)" />
22
23 <!--
24 We need the firewall on Windows XP SP2 or later.
25 -->
26 <InstallExecuteSequence>
27 <Custom Action="$(var.Prefix)SchedFirewallExceptionsUninstall$(var.Suffix)" Before="RemoveFiles" Overridable="yes" Condition="VersionNT &gt;= 600 OR (VersionNT &gt;= 501 AND ((MsiNTProductType = 1 AND ServicePackLevel &gt;= 2) OR (MsiNTProductType &gt; 1 AND ServicePackLevel &gt;= 1)))" />
28 <Custom Action="$(var.Prefix)SchedFirewallExceptionsInstall$(var.Suffix)" After="InstallFiles" Overridable="yes" Condition="VersionNT &gt;= 600 OR (VersionNT &gt;= 501 AND ((MsiNTProductType = 1 AND ServicePackLevel &gt;= 2) OR (MsiNTProductType &gt; 1 AND ServicePackLevel &gt;= 1)))" />
29 </InstallExecuteSequence>
30 </Fragment>
31
32 <!-- Firewall Custom Action DLL Definitions -->
33 <Fragment>
34 <Binary Id="$(var.Prefix)FWCA$(var.Suffix)" SourceFile="!(bindpath.$(var.platform))fwca.dll" />
35 </Fragment>
36</Include>
diff --git a/src/ext/Firewall/wixlib/FirewallExtension_arm64.wxs b/src/ext/Firewall/wixlib/FirewallExtension_arm64.wxs
new file mode 100644
index 00000000..63cdd1e8
--- /dev/null
+++ b/src/ext/Firewall/wixlib/FirewallExtension_arm64.wxs
@@ -0,0 +1,7 @@
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">
5 <?define platform=arm64 ?>
6 <?include FirewallExtension_Platform.wxi ?>
7</Wix>
diff --git a/src/ext/Firewall/wixlib/FirewallExtension_x64.wxs b/src/ext/Firewall/wixlib/FirewallExtension_x64.wxs
new file mode 100644
index 00000000..842aedf1
--- /dev/null
+++ b/src/ext/Firewall/wixlib/FirewallExtension_x64.wxs
@@ -0,0 +1,7 @@
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">
5 <?define platform=x64 ?>
6 <?include FirewallExtension_Platform.wxi ?>
7</Wix>
diff --git a/src/ext/Firewall/wixlib/FirewallExtension_x86.wxs b/src/ext/Firewall/wixlib/FirewallExtension_x86.wxs
new file mode 100644
index 00000000..5867f791
--- /dev/null
+++ b/src/ext/Firewall/wixlib/FirewallExtension_x86.wxs
@@ -0,0 +1,7 @@
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">
5 <?define platform=x86 ?>
6 <?include FirewallExtension_Platform.wxi ?>
7</Wix>
diff --git a/src/ext/Firewall/wixlib/caDecor.wxi b/src/ext/Firewall/wixlib/caDecor.wxi
new file mode 100644
index 00000000..b1711518
--- /dev/null
+++ b/src/ext/Firewall/wixlib/caDecor.wxi
@@ -0,0 +1,39 @@
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<Include xmlns="http://wixtoolset.org/schemas/v4/wxs">
5 <?ifdef Prefix ?>
6 <?undef Prefix ?>
7 <?endif?>
8
9 <?define Prefix="Wix4" ?>
10
11 <?ifndef platform ?>
12 <?define platform="x86" ?>
13 <?endif?>
14
15 <?if $(var.platform)="" ?>
16 <?undef platform ?>
17 <?define platform="x86" ?>
18 <?endif?>
19
20 <?ifdef Suffix ?>
21 <?undef Suffix ?>
22 <?endif?>
23
24 <?if $(var.platform)~="x86" ?>
25 <?define Suffix="_X86" ?>
26 <?endif?>
27
28 <?if $(var.platform)~="x64" ?>
29 <?define Suffix="_X64" ?>
30 <?endif?>
31
32 <?if $(var.platform)~="arm" ?>
33 <?define Suffix="_A32" ?>
34 <?endif?>
35
36 <?if $(var.platform)~="arm64" ?>
37 <?define Suffix="_A64" ?>
38 <?endif?>
39</Include>
diff --git a/src/ext/Firewall/wixlib/caerr.wxi b/src/ext/Firewall/wixlib/caerr.wxi
new file mode 100644
index 00000000..ff7ec121
--- /dev/null
+++ b/src/ext/Firewall/wixlib/caerr.wxi
@@ -0,0 +1,96 @@
1<Include xmlns="http://wixtoolset.org/schemas/v4/wxs">
2 <?define msierrSecureObjectsFailedCreateSD = 25520?>
3 <?define msierrSecureObjectsFailedSet = 25521?>
4 <?define msierrSecureObjectsUnknownType = 25522?>
5 <?define msierrXmlFileFailedRead = 25530?>
6 <?define msierrXmlFileFailedOpen = 25531?>
7 <?define msierrXmlFileFailedSelect = 25532?>
8 <?define msierrXmlFileFailedSave = 25533?>
9 <?define msierrXmlConfigFailedRead = 25540?>
10 <?define msierrXmlConfigFailedOpen = 25541?>
11 <?define msierrXmlConfigFailedSelect = 25542?>
12 <?define msierrXmlConfigFailedSave = 25543?>
13 <?define msierrFirewallCannotConnect = 25580?>
14 <?define msierrIISCannotConnect = 26001?>
15 <?define msierrIISFailedReadWebSite = 26002?>
16 <?define msierrIISFailedReadWebDirs = 26003?>
17 <?define msierrIISFailedReadVDirs = 26004?>
18 <?define msierrIISFailedReadFilters = 26005?>
19 <?define msierrIISFailedReadAppPool = 26006?>
20 <?define msierrIISFailedReadMimeMap = 26007?>
21 <?define msierrIISFailedReadProp = 26008?>
22 <?define msierrIISFailedReadWebSvcExt = 26009?>
23 <?define msierrIISFailedReadWebError = 26010?>
24 <?define msierrIISFailedReadHttpHeader = 26011?>
25 <?define msierrIISFailedSchedTransaction = 26031?>
26 <?define msierrIISFailedSchedInstallWebs = 26032?>
27 <?define msierrIISFailedSchedInstallWebDirs = 26033?>
28 <?define msierrIISFailedSchedInstallVDirs = 26034?>
29 <?define msierrIISFailedSchedInstallFilters = 26035?>
30 <?define msierrIISFailedSchedInstallAppPool = 26036?>
31 <?define msierrIISFailedSchedInstallProp = 26037?>
32 <?define msierrIISFailedSchedInstallWebSvcExt = 26038?>
33 <?define msierrIISFailedSchedUninstallWebs = 26051?>
34 <?define msierrIISFailedSchedUninstallWebDirs = 26052?>
35 <?define msierrIISFailedSchedUninstallVDirs = 26053?>
36 <?define msierrIISFailedSchedUninstallFilters = 26054?>
37 <?define msierrIISFailedSchedUninstallAppPool = 26055?>
38 <?define msierrIISFailedSchedUninstallProp = 26056?>
39 <?define msierrIISFailedSchedUninstallWebSvcExt = 26057?>
40 <?define msierrIISFailedStartTransaction = 26101?>
41 <?define msierrIISFailedOpenKey = 26102?>
42 <?define msierrIISFailedCreateKey = 26103?>
43 <?define msierrIISFailedWriteData = 26104?>
44 <?define msierrIISFailedCreateApp = 26105?>
45 <?define msierrIISFailedDeleteKey = 26106?>
46 <?define msierrIISFailedDeleteApp = 26107?>
47 <?define msierrIISFailedDeleteValue = 26108?>
48 <?define msierrIISFailedCommitInUse = 26109?>
49 <?define msierrSQLFailedCreateDatabase = 26201?>
50 <?define msierrSQLFailedDropDatabase = 26202?>
51 <?define msierrSQLFailedConnectDatabase = 26203?>
52 <?define msierrSQLFailedExecString = 26204?>
53 <?define msierrSQLDatabaseAlreadyExists = 26205?>
54 <?define msierrPERFMONFailedRegisterDLL = 26251?>
55 <?define msierrPERFMONFailedUnregisterDLL = 26252?>
56 <?define msierrInstallPerfCounterData = 26253?>
57 <?define msierrUninstallPerfCounterData = 26254?>
58 <?define msierrSMBFailedCreate = 26301?>
59 <?define msierrSMBFailedDrop = 26302?>
60 <?define msierrCERTFailedOpen = 26351?>
61 <?define msierrCERTFailedAdd = 26352?>
62 <?define msierrUSRFailedUserCreate = 26401?>
63 <?define msierrUSRFailedUserCreatePswd = 26402?>
64 <?define msierrUSRFailedUserGroupAdd = 26403?>
65 <?define msierrUSRFailedUserCreateExists = 26404?>
66 <?define msierrUSRFailedGrantLogonAsService = 26405?>
67 <?define msierrDependencyMissingDependencies = 26451?>
68 <?define msierrDependencyHasDependents = 26452?>
69 <?define msierrDotNetRuntimeRequired = 27000?>
70 <?define msierrComPlusCannotConnect = 28001?>
71 <?define msierrComPlusPartitionReadFailed = 28002?>
72 <?define msierrComPlusPartitionRoleReadFailed = 28003?>
73 <?define msierrComPlusUserInPartitionRoleReadFailed = 28004?>
74 <?define msierrComPlusPartitionUserReadFailed = 28005?>
75 <?define msierrComPlusApplicationReadFailed = 28006?>
76 <?define msierrComPlusApplicationRoleReadFailed = 28007?>
77 <?define msierrComPlusUserInApplicationRoleReadFailed = 28008?>
78 <?define msierrComPlusAssembliesReadFailed = 28009?>
79 <?define msierrComPlusSubscriptionReadFailed = 28010?>
80 <?define msierrComPlusPartitionDependency = 28011?>
81 <?define msierrComPlusPartitionNotFound = 28012?>
82 <?define msierrComPlusPartitionIdConflict = 28013?>
83 <?define msierrComPlusPartitionNameConflict = 28014?>
84 <?define msierrComPlusApplicationDependency = 28015?>
85 <?define msierrComPlusApplicationNotFound = 28016?>
86 <?define msierrComPlusApplicationIdConflict = 28017?>
87 <?define msierrComPlusApplicationNameConflict = 28018?>
88 <?define msierrComPlusApplicationRoleDependency = 28019?>
89 <?define msierrComPlusApplicationRoleNotFound = 28020?>
90 <?define msierrComPlusApplicationRoleConflict = 28021?>
91 <?define msierrComPlusAssemblyDependency = 28022?>
92 <?define msierrComPlusSubscriptionIdConflict = 28023?>
93 <?define msierrComPlusSubscriptionNameConflict = 28024?>
94 <?define msierrComPlusFailedLookupNames = 28025?>
95 <?define msierrMsmqCannotConnect = 28101?>
96</Include> \ No newline at end of file
diff --git a/src/ext/Firewall/wixlib/en-us.wxl b/src/ext/Firewall/wixlib/en-us.wxl
new file mode 100644
index 00000000..ab9ce8a0
--- /dev/null
+++ b/src/ext/Firewall/wixlib/en-us.wxl
@@ -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
3
4<WixLocalization Culture="en-us" xmlns="http://wixtoolset.org/schemas/v4/wxl">
5 <String Id="msierrFirewallCannotConnect" Overridable="yes">Cannot connect to Windows Firewall. ([2] [3] [4] [5])</String>
6
7 <String Id="WixSchedFirewallExceptionsInstall" Overridable="yes">Configuring Windows Firewall</String>
8 <String Id="WixSchedFirewallExceptionsUninstall" Overridable="yes">Configuring Windows Firewall</String>
9 <String Id="WixRollbackFirewallExceptionsInstall" Overridable="yes">Rolling back Windows Firewall configuration</String>
10 <String Id="WixExecFirewallExceptionsInstall" Overridable="yes">Installing Windows Firewall configuration</String>
11 <String Id="WixRollbackFirewallExceptionsUninstall" Overridable="yes">Rolling back Windows Firewall configuration</String>
12 <String Id="WixExecFirewallExceptionsUninstall" Overridable="yes">Uninstalling Windows Firewall configuration</String>
13</WixLocalization>
diff --git a/src/ext/Firewall/wixlib/es-es.wxl b/src/ext/Firewall/wixlib/es-es.wxl
new file mode 100644
index 00000000..0631b3a3
--- /dev/null
+++ b/src/ext/Firewall/wixlib/es-es.wxl
@@ -0,0 +1,12 @@
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<WixLocalization Culture="es-es" xmlns="http://wixtoolset.org/schemas/v4/wxl">
4 <String Id="msierrFirewallCannotConnect" Overridable="yes">No se puede conectar al Firewall de Windows. ([2] [3] [4] [5])</String>
5
6 <String Id="WixSchedFirewallExceptionsInstall" Overridable="yes">Configurando el Firewall de Windows</String>
7 <String Id="WixSchedFirewallExceptionsUninstall" Overridable="yes">Configurando el Firewall de Windows</String>
8 <String Id="WixRollbackFirewallExceptionsInstall" Overridable="yes">Regresando la configuración del Firewall de Windows</String>
9 <String Id="WixExecFirewallExceptionsInstall" Overridable="yes">Instalando la configuración del Firewall de Windows</String>
10 <String Id="WixRollbackFirewallExceptionsUninstall" Overridable="yes">Regresando la configuración del Firewall de Windows</String>
11 <String Id="WixExecFirewallExceptionsUninstall" Overridable="yes">Desinstalando la configuración del Firewall de Windows</String>
12</WixLocalization>
diff --git a/src/ext/Firewall/wixlib/firewall.v3.ncrunchproject b/src/ext/Firewall/wixlib/firewall.v3.ncrunchproject
new file mode 100644
index 00000000..319cd523
--- /dev/null
+++ b/src/ext/Firewall/wixlib/firewall.v3.ncrunchproject
@@ -0,0 +1,5 @@
1<ProjectConfiguration>
2 <Settings>
3 <IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
4 </Settings>
5</ProjectConfiguration> \ No newline at end of file
diff --git a/src/ext/Firewall/wixlib/firewall.wixproj b/src/ext/Firewall/wixlib/firewall.wixproj
new file mode 100644
index 00000000..242fa56e
--- /dev/null
+++ b/src/ext/Firewall/wixlib/firewall.wixproj
@@ -0,0 +1,26 @@
1<!-- Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. -->
2<Project Sdk="WixToolset.Sdk">
3
4 <PropertyGroup>
5 <OutputType>Library</OutputType>
6 <BindFiles>true</BindFiles>
7 <Cultures>en-us</Cultures>
8 </PropertyGroup>
9
10 <ItemGroup>
11 <BindInputPaths Include="$(OutputPath)x86" BindName='x86' />
12 <BindInputPaths Include="$(OutputPath)x64" BindName='x64' />
13 <BindInputPaths Include="$(OutputPath)arm64" BindName='arm64' />
14 </ItemGroup>
15
16 <ItemGroup>
17 <ProjectReference Include="..\ca\fwca.vcxproj" Properties="Platform=ARM64" />
18 <ProjectReference Include="..\ca\fwca.vcxproj" Properties="Platform=x86" />
19 <ProjectReference Include="..\ca\fwca.vcxproj" Properties="Platform=x64" />
20 </ItemGroup>
21
22 <ItemGroup>
23 <PackageReference Include="Nerdbank.GitVersioning" Version="3.3.37" PrivateAssets="All" />
24 </ItemGroup>
25
26</Project>
diff --git a/src/ext/Firewall/wixlib/ja-jp.wxl b/src/ext/Firewall/wixlib/ja-jp.wxl
new file mode 100644
index 00000000..a4036c7e
--- /dev/null
+++ b/src/ext/Firewall/wixlib/ja-jp.wxl
@@ -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
3
4<WixLocalization Culture="ja-jp" xmlns="http://wixtoolset.org/schemas/v4/wxl">
5 <String Id="msierrFirewallCannotConnect" Overridable="yes">Windows ファイアウォールへ接続できません。 ([2] [3] [4] [5])</String>
6
7 <String Id="WixSchedFirewallExceptionsInstall" Overridable="yes">Windows ファイアウォールを構成しています</String>
8 <String Id="WixSchedFirewallExceptionsUninstall" Overridable="yes">Windows ファイアウォールを構成しています</String>
9 <String Id="WixRollbackFirewallExceptionsInstall" Overridable="yes">Windows ファイアウォール構成をロールバックしています</String>
10 <String Id="WixExecFirewallExceptionsInstall" Overridable="yes">Windows ファイアウォール構成をインストールしています</String>
11 <String Id="WixRollbackFirewallExceptionsUninstall" Overridable="yes">Windows ファイアウォール構成をロールバックしています</String>
12 <String Id="WixExecFirewallExceptionsUninstall" Overridable="yes">Windows ファイアウォール構成をアンインストールしています</String>
13</WixLocalization>
diff --git a/src/ext/Firewall/wixlib/pl-pl.wxl b/src/ext/Firewall/wixlib/pl-pl.wxl
new file mode 100644
index 00000000..1b37460e
--- /dev/null
+++ b/src/ext/Firewall/wixlib/pl-pl.wxl
@@ -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
3
4<WixLocalization Culture="pl-pl" xmlns="http://wixtoolset.org/schemas/v4/wxl">
5 <String Id="msierrFirewallCannotConnect" Overridable="yes">Nie udało się połączyć z Zaporą systemu Windows. ([2] [3] [4] [5])</String>
6
7 <String Id="WixSchedFirewallExceptionsInstall" Overridable="yes">Dodawanie wyjątków do Zapory systemu Windows</String>
8 <String Id="WixSchedFirewallExceptionsUninstall" Overridable="yes">Usuwanie wyjątków z Zapory systemu Windows</String>
9 <String Id="WixRollbackFirewallExceptionsInstall" Overridable="yes">Cofanie zmian konfiguracji Zapory systemu Windows</String>
10 <String Id="WixExecFirewallExceptionsInstall" Overridable="yes">Konfigurowywanie Zapory systemu Windows</String>
11 <String Id="WixRollbackFirewallExceptionsUninstall" Overridable="yes">Cofanie zmian konfiguracji Zapory systemu Windows</String>
12 <String Id="WixExecFirewallExceptionsUninstall" Overridable="yes">Konfigurowywanie Zapory systemu Windows</String>
13</WixLocalization>