From ba00d844a2e2716a6aa07df89dd9318608bd1909 Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Tue, 4 May 2021 22:46:07 -0700 Subject: Move Firewall.wixext into ext --- src/ext/Firewall/CSharp.Build.props | 11 + src/ext/Firewall/Cpp.Build.props | 86 ++ src/ext/Firewall/Directory.Build.props | 29 + src/ext/Firewall/Directory.Build.targets | 48 + src/ext/Firewall/Firewall.wixext.sln | 73 ++ .../Firewall/Firewall.wixext.v3.ncrunchsolution | 6 + src/ext/Firewall/README.md | 2 + src/ext/Firewall/appveyor.cmd | 14 + src/ext/Firewall/appveyor.yml | 40 + src/ext/Firewall/ca/CustomMsiErrors.h | 130 +++ src/ext/Firewall/ca/caDecor.h | 13 + src/ext/Firewall/ca/cost.h | 5 + src/ext/Firewall/ca/dllmain.cpp | 26 + src/ext/Firewall/ca/firewall.cpp | 1085 ++++++++++++++++++++ src/ext/Firewall/ca/fwca.def | 9 + src/ext/Firewall/ca/fwca.v3.ncrunchproject | 5 + src/ext/Firewall/ca/fwca.vcxproj | 81 ++ src/ext/Firewall/ca/packages.config | 5 + src/ext/Firewall/ca/precomp.h | 19 + src/ext/Firewall/nuget.config | 18 + .../FirewallExtensionFixture.cs | 80 ++ .../TestData/UsingFirewall/Package.en-us.wxl | 11 + .../TestData/UsingFirewall/Package.wxs | 15 + .../TestData/UsingFirewall/PackageComponents.wxs | 14 + .../TestData/UsingFirewall/example.txt | 1 + .../UsingOutboundFirewall/Package.en-us.wxl | 11 + .../TestData/UsingOutboundFirewall/Package.wxs | 15 + .../UsingOutboundFirewall/PackageComponents.wxs | 14 + .../TestData/UsingOutboundFirewall/example.txt | 1 + .../WixToolsetTest.Firewall.csproj | 45 + .../WixToolsetTest.Firewall.v3.ncrunchproject | 5 + src/ext/Firewall/wix.snk | Bin 0 -> 596 bytes src/ext/Firewall/wixext/FirewallCompiler.cs | 354 +++++++ src/ext/Firewall/wixext/FirewallConstants.cs | 23 + src/ext/Firewall/wixext/FirewallDecompiler.cs | 182 ++++ src/ext/Firewall/wixext/FirewallErrors.cs | 36 + src/ext/Firewall/wixext/FirewallExtensionData.cs | 23 + .../Firewall/wixext/FirewallExtensionFactory.cs | 18 + .../Firewall/wixext/FirewallTableDefinitions.cs | 34 + .../FirewallWindowsInstallerBackendExtension.cs | 13 + .../wixext/Symbols/FirewallSymbolDefinitions.cs | 39 + .../wixext/Symbols/WixFirewallExceptionSymbol.cs | 119 +++ .../wixext/WixToolset.Firewall.wixext.csproj | 31 + .../wixext/WixToolset.Firewall.wixext.targets | 11 + src/ext/Firewall/wixlib/FirewallExtension.wxs | 11 + .../Firewall/wixlib/FirewallExtension_Platform.wxi | 36 + .../Firewall/wixlib/FirewallExtension_arm64.wxs | 7 + src/ext/Firewall/wixlib/FirewallExtension_x64.wxs | 7 + src/ext/Firewall/wixlib/FirewallExtension_x86.wxs | 7 + src/ext/Firewall/wixlib/caDecor.wxi | 39 + src/ext/Firewall/wixlib/caerr.wxi | 96 ++ src/ext/Firewall/wixlib/en-us.wxl | 13 + src/ext/Firewall/wixlib/es-es.wxl | 12 + src/ext/Firewall/wixlib/firewall.v3.ncrunchproject | 5 + src/ext/Firewall/wixlib/firewall.wixproj | 26 + src/ext/Firewall/wixlib/ja-jp.wxl | 13 + src/ext/Firewall/wixlib/pl-pl.wxl | 13 + src/ext/global.json | 5 + 58 files changed, 3090 insertions(+) create mode 100644 src/ext/Firewall/CSharp.Build.props create mode 100644 src/ext/Firewall/Cpp.Build.props create mode 100644 src/ext/Firewall/Directory.Build.props create mode 100644 src/ext/Firewall/Directory.Build.targets create mode 100644 src/ext/Firewall/Firewall.wixext.sln create mode 100644 src/ext/Firewall/Firewall.wixext.v3.ncrunchsolution create mode 100644 src/ext/Firewall/README.md create mode 100644 src/ext/Firewall/appveyor.cmd create mode 100644 src/ext/Firewall/appveyor.yml create mode 100644 src/ext/Firewall/ca/CustomMsiErrors.h create mode 100644 src/ext/Firewall/ca/caDecor.h create mode 100644 src/ext/Firewall/ca/cost.h create mode 100644 src/ext/Firewall/ca/dllmain.cpp create mode 100644 src/ext/Firewall/ca/firewall.cpp create mode 100644 src/ext/Firewall/ca/fwca.def create mode 100644 src/ext/Firewall/ca/fwca.v3.ncrunchproject create mode 100644 src/ext/Firewall/ca/fwca.vcxproj create mode 100644 src/ext/Firewall/ca/packages.config create mode 100644 src/ext/Firewall/ca/precomp.h create mode 100644 src/ext/Firewall/nuget.config create mode 100644 src/ext/Firewall/test/WixToolsetTest.Firewall/FirewallExtensionFixture.cs create mode 100644 src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/Package.en-us.wxl create mode 100644 src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/Package.wxs create mode 100644 src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/PackageComponents.wxs create mode 100644 src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingFirewall/example.txt create mode 100644 src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/Package.en-us.wxl create mode 100644 src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/Package.wxs create mode 100644 src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/PackageComponents.wxs create mode 100644 src/ext/Firewall/test/WixToolsetTest.Firewall/TestData/UsingOutboundFirewall/example.txt create mode 100644 src/ext/Firewall/test/WixToolsetTest.Firewall/WixToolsetTest.Firewall.csproj create mode 100644 src/ext/Firewall/test/WixToolsetTest.Firewall/WixToolsetTest.Firewall.v3.ncrunchproject create mode 100644 src/ext/Firewall/wix.snk create mode 100644 src/ext/Firewall/wixext/FirewallCompiler.cs create mode 100644 src/ext/Firewall/wixext/FirewallConstants.cs create mode 100644 src/ext/Firewall/wixext/FirewallDecompiler.cs create mode 100644 src/ext/Firewall/wixext/FirewallErrors.cs create mode 100644 src/ext/Firewall/wixext/FirewallExtensionData.cs create mode 100644 src/ext/Firewall/wixext/FirewallExtensionFactory.cs create mode 100644 src/ext/Firewall/wixext/FirewallTableDefinitions.cs create mode 100644 src/ext/Firewall/wixext/FirewallWindowsInstallerBackendExtension.cs create mode 100644 src/ext/Firewall/wixext/Symbols/FirewallSymbolDefinitions.cs create mode 100644 src/ext/Firewall/wixext/Symbols/WixFirewallExceptionSymbol.cs create mode 100644 src/ext/Firewall/wixext/WixToolset.Firewall.wixext.csproj create mode 100644 src/ext/Firewall/wixext/WixToolset.Firewall.wixext.targets create mode 100644 src/ext/Firewall/wixlib/FirewallExtension.wxs create mode 100644 src/ext/Firewall/wixlib/FirewallExtension_Platform.wxi create mode 100644 src/ext/Firewall/wixlib/FirewallExtension_arm64.wxs create mode 100644 src/ext/Firewall/wixlib/FirewallExtension_x64.wxs create mode 100644 src/ext/Firewall/wixlib/FirewallExtension_x86.wxs create mode 100644 src/ext/Firewall/wixlib/caDecor.wxi create mode 100644 src/ext/Firewall/wixlib/caerr.wxi create mode 100644 src/ext/Firewall/wixlib/en-us.wxl create mode 100644 src/ext/Firewall/wixlib/es-es.wxl create mode 100644 src/ext/Firewall/wixlib/firewall.v3.ncrunchproject create mode 100644 src/ext/Firewall/wixlib/firewall.wixproj create mode 100644 src/ext/Firewall/wixlib/ja-jp.wxl create mode 100644 src/ext/Firewall/wixlib/pl-pl.wxl create mode 100644 src/ext/global.json (limited to 'src/ext') 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 @@ + + + + + true + $([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)wix.snk)) + + 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 @@ + + + + + + Win32 + $(BaseIntermediateOutputPath)$(Configuration)\$(Platform)\ + $(OutputPath)$(Platform)\ + + + + $([Microsoft.Build.Utilities.ToolLocationHelper]::GetLatestSDKTargetPlatformVersion('Windows', '10.0')) + + + + + $(DisableSpecificCompilerWarnings) + Level4 + $(ProjectDir)inc;$(MSBuildProjectDirectory);$(IntDir);$(SqlCESdkIncludePath);$(ProjectAdditionalIncludeDirectories);%(AdditionalIncludeDirectories) + WIN32;_WINDOWS;_WIN32_MSI=500;_WIN32_WINNT=0x0501;$(ArmPreprocessorDefinitions);$(UnicodePreprocessorDefinitions);_CRT_STDIO_LEGACY_WIDE_SPECIFIERS;_WINSOCK_DEPRECATED_NO_WARNINGS;%(PreprocessorDefinitions) + Use + precomp.h + StdCall + true + false + -YlprecompDefine + /Zc:threadSafeInit- %(AdditionalOptions) + true + + + $(ArmPreprocessorDefinitions);%(PreprocessorDefinitions) + $(ProjectAdditionalResourceIncludeDirectories);%(AdditionalIncludeDirectories) + + + $(OutDir);$(AdditionalMultiTargetLibraryPath);$(ProjectAdditionalLibraryDirectories);%(AdditionalLibraryDirectories) + + + $(ProjectSubSystem) + $(ProjectModuleDefinitionFile) + $(ResourceOnlyDll) + true + $(ProjectAdditionalLinkLibraries);advapi32.lib;comdlg32.lib;user32.lib;oleaut32.lib;gdi32.lib;shell32.lib;ole32.lib;version.lib;%(AdditionalDependencies) + $(OutDir);$(AdditionalMultiTargetLibraryPath);$(ArmLibraryDirectories);$(ProjectAdditionalLinkLibraryDirectories);%(AdditionalLibraryDirectories) + /IGNORE:4099 %(AdditionalOptions) + + + + + + NoExtensions + + + + + CDecl + + + + + OldStyle + true + true + + + + + Disabled + EnableFastChecks + _DEBUG;DEBUG;%(PreprocessorDefinitions) + MultiThreadedDebug + + + + + MinSpace + NDEBUG;%(PreprocessorDefinitions) + true + true + MultiThreaded + + + true + true + + + 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 @@ + + + + + + Debug + false + MSB3246 + + $(MSBuildProjectName) + $([System.IO.Path]::GetFullPath($(MSBuildThisFileDirectory)..\build\)) + $(BaseOutputPath)obj\$(ProjectName)\ + $(BaseOutputPath)$(Configuration)\ + + WiX Toolset Team + WiX Toolset + Copyright (c) .NET Foundation and contributors. All rights reserved. + MS-RL + WiX Toolset + + + + + + + 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 @@ + + + + + + + true + $(SolutionPath) + $(NCrunchOriginalSolutionPath) + + + + + + + $([System.IO.File]::ReadAllText($(TheSolutionPath))) + $([System.IO.Path]::GetDirectoryName( $(TheSolutionPath) )) + (?<="[PackageName]", ")(.*)(?=", ") + + + + + + %(Identity) + $(SolutionFileContent.Contains('\%(Identity).csproj')) + + + + + $(RegexPattern.Replace('[PackageName]','%(PackageName)') ) + $([System.Text.RegularExpressions.Regex]::Match('$(SolutionFileContent)', '%(Pattern)')) + + + + + + + + + + + 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 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27130.2003 +MinimumVisualStudioVersion = 15.0.26124.0 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fwca", "src\ca\fwca.vcxproj", "{F72D34CA-48DA-4DFD-91A9-A0C78BEF6981}" +EndProject +Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "firewall", "src\wixlib\firewall.wixproj", "{1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolset.Firewall.wixext", "src\wixext\WixToolset.Firewall.wixext.csproj", "{6CF033EB-0A39-4AC6-9D41-9BD506352045}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WixToolsetTest.Firewall", "src\test\WixToolsetTest.Firewall\WixToolsetTest.Firewall.csproj", "{D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F72D34CA-48DA-4DFD-91A9-A0C78BEF6981}.Debug|Any CPU.ActiveCfg = Debug|Win32 + {F72D34CA-48DA-4DFD-91A9-A0C78BEF6981}.Debug|Any CPU.Build.0 = Debug|Win32 + {F72D34CA-48DA-4DFD-91A9-A0C78BEF6981}.Debug|x64.ActiveCfg = Debug|Win32 + {F72D34CA-48DA-4DFD-91A9-A0C78BEF6981}.Debug|x86.ActiveCfg = Debug|Win32 + {F72D34CA-48DA-4DFD-91A9-A0C78BEF6981}.Debug|x86.Build.0 = Debug|Win32 + {F72D34CA-48DA-4DFD-91A9-A0C78BEF6981}.Release|Any CPU.ActiveCfg = Release|Win32 + {F72D34CA-48DA-4DFD-91A9-A0C78BEF6981}.Release|x64.ActiveCfg = Release|Win32 + {F72D34CA-48DA-4DFD-91A9-A0C78BEF6981}.Release|x86.ActiveCfg = Release|Win32 + {F72D34CA-48DA-4DFD-91A9-A0C78BEF6981}.Release|x86.Build.0 = Release|Win32 + {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Debug|Any CPU.ActiveCfg = Debug|x86 + {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Debug|Any CPU.Build.0 = Debug|x86 + {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Debug|x64.ActiveCfg = Debug|x86 + {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Debug|x86.ActiveCfg = Debug|x86 + {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Debug|x86.Build.0 = Debug|x86 + {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Release|Any CPU.ActiveCfg = Release|x86 + {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Release|x64.ActiveCfg = Release|x86 + {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Release|x86.ActiveCfg = Release|x86 + {1ACFFEFD-505A-41A5-ACBF-A02B7B473AA2}.Release|x86.Build.0 = Release|x86 + {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Debug|x64.ActiveCfg = Debug|Any CPU + {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Debug|x64.Build.0 = Debug|Any CPU + {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Debug|x86.ActiveCfg = Debug|Any CPU + {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Debug|x86.Build.0 = Debug|Any CPU + {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Release|Any CPU.Build.0 = Release|Any CPU + {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Release|x64.ActiveCfg = Release|Any CPU + {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Release|x64.Build.0 = Release|Any CPU + {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Release|x86.ActiveCfg = Release|Any CPU + {6CF033EB-0A39-4AC6-9D41-9BD506352045}.Release|x86.Build.0 = Release|Any CPU + {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Debug|x64.ActiveCfg = Debug|Any CPU + {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Debug|x64.Build.0 = Debug|Any CPU + {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Debug|x86.ActiveCfg = Debug|Any CPU + {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Debug|x86.Build.0 = Debug|Any CPU + {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Release|Any CPU.Build.0 = Release|Any CPU + {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Release|x64.ActiveCfg = Release|Any CPU + {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Release|x64.Build.0 = Release|Any CPU + {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Release|x86.ActiveCfg = Release|Any CPU + {D5D34EC4-AF91-4B11-AC0A-FA5242AE924B}.Release|x86.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E4566A6B-47D0-4EA0-989A-D763AC39105D} + EndGlobalSection +EndGlobal 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 @@ + + + True + True + + \ 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 @@ +# Firewall.wixext +WixToolset.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 @@ +@setlocal +@pushd %~dp0 + +nuget restore || exit /b + +msbuild -p:Configuration=Release -t:Restore || exit /b + +msbuild -p:Configuration=Release src\test\WixToolsetTest.Firewall\WixToolsetTest.Firewall.csproj || exit /b +dotnet test -c Release --no-build src\test\WixToolsetTest.Firewall || exit /b + +msbuild -p:Configuration=Release -t:Pack src\wixext\WixToolset.Firewall.wixext.csproj || exit /b + +@popd +@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 @@ +# 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. +# +# Do NOT modify this file. Update the canonical version in Home\repo-template\src\appveyor.yml +# then update all of the repos. + +branches: + only: + - master + - develop + +image: Visual Studio 2019 + +version: 0.0.0.{build} +configuration: Release + +environment: + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + DOTNET_CLI_TELEMETRY_OPTOUT: 1 + NUGET_XMLDOC_MODE: skip + +build_script: + - appveyor.cmd + +pull_requests: + do_not_increment_build_number: true + +nuget: + disable_publish_on_pr: true + +skip_branch_with_pr: true +skip_tags: true + +artifacts: +- path: build\Release\**\*.nupkg + name: nuget + +notifications: +- provider: Slack + incoming_webhook: + 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 @@ +#pragma once +// 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. + + +#define GLOBAL_ERROR_BASE 25501 + +#define msierrSecureObjectsFailedCreateSD 25520 +#define msierrSecureObjectsFailedSet 25521 +#define msierrSecureObjectsUnknownType 25522 + +#define msierrXmlFileFailedRead 25530 +#define msierrXmlFileFailedOpen 25531 +#define msierrXmlFileFailedSelect 25532 +#define msierrXmlFileFailedSave 25533 + +#define msierrXmlConfigFailedRead 25540 +#define msierrXmlConfigFailedOpen 25541 +#define msierrXmlConfigFailedSelect 25542 +#define msierrXmlConfigFailedSave 25543 + +#define msierrFirewallCannotConnect 25580 + +//--------------------------------------------------------------------------- +// Server CustomAction Errors +// SERVER range: 26001-26100 +#define SERVER_ERROR_BASE 26000 + +#define msierrIISCannotConnect 26001 +#define msierrIISFailedReadWebSite 26002 +#define msierrIISFailedReadWebDirs 26003 +#define msierrIISFailedReadVDirs 26004 +#define msierrIISFailedReadFilters 26005 +#define msierrIISFailedReadAppPool 26006 +#define msierrIISFailedReadMimeMap 26007 +#define msierrIISFailedReadProp 26008 +#define msierrIISFailedReadWebSvcExt 26009 +#define msierrIISFailedReadWebError 26010 +#define msierrIISFailedReadHttpHeader 26011 + +#define msierrIISFailedSchedTransaction 26031 +#define msierrIISFailedSchedInstallWebs 26032 +#define msierrIISFailedSchedInstallWebDirs 26033 +#define msierrIISFailedSchedInstallVDirs 26034 +#define msierrIISFailedSchedInstallFilters 26035 +#define msierrIISFailedSchedInstallAppPool 26036 +#define msierrIISFailedSchedInstallProp 26037 +#define msierrIISFailedSchedInstallWebSvcExt 26038 + +#define msierrIISFailedSchedUninstallWebs 26051 +#define msierrIISFailedSchedUninstallWebDirs 26052 +#define msierrIISFailedSchedUninstallVDirs 26053 +#define msierrIISFailedSchedUninstallFilters 26054 +#define msierrIISFailedSchedUninstallAppPool 26055 +#define msierrIISFailedSchedUninstallProp 26056 +#define msierrIISFailedSchedUninstallWebSvcExt 26057 + +#define msierrIISFailedStartTransaction 26101 +#define msierrIISFailedOpenKey 26102 +#define msierrIISFailedCreateKey 26103 +#define msierrIISFailedWriteData 26104 +#define msierrIISFailedCreateApp 26105 +#define msierrIISFailedDeleteKey 26106 +#define msierrIISFailedDeleteApp 26107 +#define msierrIISFailedDeleteValue 26108 +#define msierrIISFailedCommitInUse 26109 + +#define msierrSQLFailedCreateDatabase 26201 +#define msierrSQLFailedDropDatabase 26202 +#define msierrSQLFailedConnectDatabase 26203 +#define msierrSQLFailedExecString 26204 +#define msierrSQLDatabaseAlreadyExists 26205 + +#define msierrPERFMONFailedRegisterDLL 26251 +#define msierrPERFMONFailedUnregisterDLL 26252 +#define msierrInstallPerfCounterData 26253 +#define msierrUninstallPerfCounterData 26254 + +#define msierrSMBFailedCreate 26301 +#define msierrSMBFailedDrop 26302 + +#define msierrCERTFailedOpen 26351 +#define msierrCERTFailedAdd 26352 + +#define msierrUSRFailedUserCreate 26401 +#define msierrUSRFailedUserCreatePswd 26402 +#define msierrUSRFailedUserGroupAdd 26403 +#define msierrUSRFailedUserCreateExists 26404 +#define msierrUSRFailedGrantLogonAsService 26405 + +#define msierrDependencyMissingDependencies 26451 +#define msierrDependencyHasDependents 26452 + +//-------------------------------------------------------------------------- +// Managed code CustomAction Errors +// MANAGED range: 27000-27100 +#define MANAGED_ERROR_BASE 27000 + +#define msierrDotNetRuntimeRequired 27000 +//--------------------------------------------------------------------------- +// Public CustomAction Errors +// PUBLIC range: 28001-28100 +#define PUBLIC_ERROR_BASE 28000 + +#define msierrComPlusCannotConnect 28001 +#define msierrComPlusPartitionReadFailed 28002 +#define msierrComPlusPartitionRoleReadFailed 28003 +#define msierrComPlusUserInPartitionRoleReadFailed 28004 +#define msierrComPlusPartitionUserReadFailed 28005 +#define msierrComPlusApplicationReadFailed 28006 +#define msierrComPlusApplicationRoleReadFailed 28007 +#define msierrComPlusUserInApplicationRoleReadFailed 28008 +#define msierrComPlusAssembliesReadFailed 28009 +#define msierrComPlusSubscriptionReadFailed 28010 +#define msierrComPlusPartitionDependency 28011 +#define msierrComPlusPartitionNotFound 28012 +#define msierrComPlusPartitionIdConflict 28013 +#define msierrComPlusPartitionNameConflict 28014 +#define msierrComPlusApplicationDependency 28015 +#define msierrComPlusApplicationNotFound 28016 +#define msierrComPlusApplicationIdConflict 28017 +#define msierrComPlusApplicationNameConflict 28018 +#define msierrComPlusApplicationRoleDependency 28019 +#define msierrComPlusApplicationRoleNotFound 28020 +#define msierrComPlusApplicationRoleConflict 28021 +#define msierrComPlusAssemblyDependency 28022 +#define msierrComPlusSubscriptionIdConflict 28023 +#define msierrComPlusSubscriptionNameConflict 28024 +#define msierrComPlusFailedLookupNames 28025 + +#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 @@ +#pragma once +// 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. + + +#if defined(_M_ARM64) +#define CUSTOM_ACTION_DECORATION(f) L"Wix4" f L"_A64" +#elif defined(_M_AMD64) +#define CUSTOM_ACTION_DECORATION(f) L"Wix4" f L"_X64" +#elif defined(_M_ARM) +#define CUSTOM_ACTION_DECORATION(f) L"Wix4" f L"_ARM" +#else +#define CUSTOM_ACTION_DECORATION(f) L"Wix4" f L"_X86" +#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 @@ +#pragma once +// 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. + + +const 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 @@ +// 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. + +#include "precomp.h" + +/******************************************************************** +DllMain - standard entry point for all WiX CustomActions + +********************************************************************/ +extern "C" BOOL WINAPI DllMain( + IN HINSTANCE hInst, + IN ULONG ulReason, + IN LPVOID) +{ + switch(ulReason) + { + case DLL_PROCESS_ATTACH: + WcaGlobalInitialize(hInst); + break; + + case DLL_PROCESS_DETACH: + WcaGlobalFinalize(); + break; + } + + return TRUE; +} 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 @@ +// 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. + +#include "precomp.h" + +LPCWSTR vcsFirewallExceptionQuery = + L"SELECT `Name`, `RemoteAddresses`, `Port`, `Protocol`, `Program`, `Attributes`, `Profile`, `Component_`, `Description`, `Direction` FROM `Wix4FirewallException`"; +enum eFirewallExceptionQuery { feqName = 1, feqRemoteAddresses, feqPort, feqProtocol, feqProgram, feqAttributes, feqProfile, feqComponent, feqDescription }; +enum eFirewallExceptionTarget { fetPort = 1, fetApplication, fetUnknown }; +enum eFirewallExceptionAttributes { feaIgnoreFailures = 1 }; + +/****************************************************************** + SchedFirewallExceptions - immediate custom action worker to + register and remove firewall exceptions. + +********************************************************************/ +static UINT SchedFirewallExceptions( + __in MSIHANDLE hInstall, + WCA_TODO todoSched + ) +{ + HRESULT hr = S_OK; + UINT er = ERROR_SUCCESS; + int cFirewallExceptions = 0; + + PMSIHANDLE hView = NULL; + PMSIHANDLE hRec = NULL; + + LPWSTR pwzCustomActionData = NULL; + LPWSTR pwzName = NULL; + LPWSTR pwzRemoteAddresses = NULL; + LPWSTR pwzPort = NULL; + int iProtocol = 0; + int iAttributes = 0; + int iProfile = 0; + LPWSTR pwzProgram = NULL; + LPWSTR pwzComponent = NULL; + LPWSTR pwzFormattedFile = NULL; + LPWSTR pwzDescription = NULL; + int iDirection = 0; + + // initialize + hr = WcaInitialize(hInstall, "SchedFirewallExceptions"); + ExitOnFailure(hr, "failed to initialize"); + + // anything to do? + if (S_OK != WcaTableExists(L"Wix4FirewallException")) + { + WcaLog(LOGMSG_STANDARD, "Wix4FirewallException table doesn't exist, so there are no firewall exceptions to configure."); + ExitFunction(); + } + + // query and loop through all the firewall exceptions + hr = WcaOpenExecuteView(vcsFirewallExceptionQuery, &hView); + ExitOnFailure(hr, "failed to open view on Wix4FirewallException table"); + + while (S_OK == (hr = WcaFetchRecord(hView, &hRec))) + { + hr = WcaGetRecordFormattedString(hRec, feqName, &pwzName); + ExitOnFailure(hr, "failed to get firewall exception name"); + + hr = WcaGetRecordFormattedString(hRec, feqRemoteAddresses, &pwzRemoteAddresses); + ExitOnFailure(hr, "failed to get firewall exception remote addresses"); + + hr = WcaGetRecordFormattedString(hRec, feqPort, &pwzPort); + ExitOnFailure(hr, "failed to get firewall exception port"); + + hr = WcaGetRecordInteger(hRec, feqProtocol, &iProtocol); + ExitOnFailure(hr, "failed to get firewall exception protocol"); + + hr = WcaGetRecordFormattedString(hRec, feqProgram, &pwzProgram); + ExitOnFailure(hr, "failed to get firewall exception program"); + + hr = WcaGetRecordInteger(hRec, feqAttributes, &iAttributes); + ExitOnFailure(hr, "failed to get firewall exception attributes"); + + hr = WcaGetRecordInteger(hRec, feqProfile, &iProfile); + ExitOnFailure(hr, "failed to get firewall exception profile"); + + hr = WcaGetRecordString(hRec, feqComponent, &pwzComponent); + ExitOnFailure(hr, "failed to get firewall exception component"); + + hr = WcaGetRecordString(hRec, feqDescription, &pwzDescription); + ExitOnFailure(hr, "failed to get firewall description"); + + // figure out what we're doing for this exception, treating reinstall the same as install + WCA_TODO todoComponent = WcaGetComponentToDo(pwzComponent); + if ((WCA_TODO_REINSTALL == todoComponent ? WCA_TODO_INSTALL : todoComponent) != todoSched) + { + WcaLog(LOGMSG_STANDARD, "Component '%ls' action state (%d) doesn't match request (%d)", pwzComponent, todoComponent, todoSched); + continue; + } + + // action :: name :: profile :: remoteaddresses :: attributes :: target :: {port::protocol | path} + ++cFirewallExceptions; + hr = WcaWriteIntegerToCaData(todoComponent, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write exception action to custom action data"); + + hr = WcaWriteStringToCaData(pwzName, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write exception name to custom action data"); + + hr = WcaWriteIntegerToCaData(iProfile, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write exception profile to custom action data"); + + hr = WcaWriteStringToCaData(pwzRemoteAddresses, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write exception remote addresses to custom action data"); + + hr = WcaWriteIntegerToCaData(iAttributes, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write exception attributes to custom action data"); + + if (*pwzProgram) + { + // If program is defined, we have an application exception. + hr = WcaWriteIntegerToCaData(fetApplication, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write exception target (application) to custom action data"); + + hr = WcaWriteStringToCaData(pwzProgram, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write application path to custom action data"); + } + else + { + // we have a port-only exception + hr = WcaWriteIntegerToCaData(fetPort, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write exception target (port) to custom action data"); + } + + hr = WcaWriteStringToCaData(pwzPort, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write application path to custom action data"); + + hr = WcaWriteIntegerToCaData(iProtocol, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write exception protocol to custom action data"); + + hr = WcaWriteStringToCaData(pwzDescription, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write firewall rule description to custom action data"); + + hr = WcaWriteIntegerToCaData(iDirection, &pwzCustomActionData); + ExitOnFailure(hr, "failed to write firewall rule direction to custom action data"); + } + + // reaching the end of the list is actually a good thing, not an error + if (E_NOMOREITEMS == hr) + { + hr = S_OK; + } + ExitOnFailure(hr, "failure occured while processing Wix4FirewallException table"); + + // schedule ExecFirewallExceptions if there's anything to do + if (pwzCustomActionData && *pwzCustomActionData) + { + WcaLog(LOGMSG_STANDARD, "Scheduling firewall exception (%ls)", pwzCustomActionData); + + if (WCA_TODO_INSTALL == todoSched) + { + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackFirewallExceptionsInstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION); + ExitOnFailure(hr, "failed to schedule firewall install exceptions rollback"); + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecFirewallExceptionsInstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION); + ExitOnFailure(hr, "failed to schedule firewall install exceptions execution"); + } + else + { + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackFirewallExceptionsUninstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION); + ExitOnFailure(hr, "failed to schedule firewall uninstall exceptions rollback"); + hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecFirewallExceptionsUninstall"), pwzCustomActionData, cFirewallExceptions * COST_FIREWALL_EXCEPTION); + ExitOnFailure(hr, "failed to schedule firewall uninstall exceptions execution"); + } + } + else + { + WcaLog(LOGMSG_STANDARD, "No firewall exceptions scheduled"); + } + +LExit: + ReleaseStr(pwzCustomActionData); + ReleaseStr(pwzName); + ReleaseStr(pwzRemoteAddresses); + ReleaseStr(pwzPort); + ReleaseStr(pwzProgram); + ReleaseStr(pwzComponent); + ReleaseStr(pwzDescription); + ReleaseStr(pwzFormattedFile); + + return WcaFinalize(er = FAILED(hr) ? ERROR_INSTALL_FAILURE : er); +} + +/****************************************************************** + SchedFirewallExceptionsInstall - immediate custom action entry + point to register firewall exceptions. + +********************************************************************/ +extern "C" UINT __stdcall SchedFirewallExceptionsInstall( + __in MSIHANDLE hInstall + ) +{ + return SchedFirewallExceptions(hInstall, WCA_TODO_INSTALL); +} + +/****************************************************************** + SchedFirewallExceptionsUninstall - immediate custom action entry + point to remove firewall exceptions. + +********************************************************************/ +extern "C" UINT __stdcall SchedFirewallExceptionsUninstall( + __in MSIHANDLE hInstall + ) +{ + return SchedFirewallExceptions(hInstall, WCA_TODO_UNINSTALL); +} + +/****************************************************************** + GetFirewallRules - Get the collection of firewall rules. + +********************************************************************/ +static HRESULT GetFirewallRules( + __in BOOL fIgnoreFailures, + __out INetFwRules** ppNetFwRules + ) +{ + HRESULT hr = S_OK; + INetFwPolicy2* pNetFwPolicy2 = NULL; + INetFwRules* pNetFwRules = NULL; + *ppNetFwRules = NULL; + + do + { + ReleaseNullObject(pNetFwPolicy2); + ReleaseNullObject(pNetFwRules); + + if (SUCCEEDED(hr = ::CoCreateInstance(__uuidof(NetFwPolicy2), NULL, CLSCTX_ALL, __uuidof(INetFwPolicy2), (void**)&pNetFwPolicy2)) && + SUCCEEDED(hr = pNetFwPolicy2->get_Rules(&pNetFwRules))) + { + break; + } + else if (fIgnoreFailures) + { + ExitFunction1(hr = S_FALSE); + } + else + { + WcaLog(LOGMSG_STANDARD, "Failed to connect to Windows Firewall"); + UINT er = WcaErrorMessage(msierrFirewallCannotConnect, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); + switch (er) + { + case IDABORT: // exit with the current HRESULT + ExitFunction(); + case IDRETRY: // clean up and retry the loop + hr = S_FALSE; + break; + case IDIGNORE: // pass S_FALSE back to the caller, who knows how to ignore the failure + ExitFunction1(hr = S_FALSE); + default: // No UI, so default is to fail. + ExitFunction(); + } + } + } while (S_FALSE == hr); + + *ppNetFwRules = pNetFwRules; + pNetFwRules = NULL; + +LExit: + ReleaseObject(pNetFwPolicy2); + ReleaseObject(pNetFwRules); + + return hr; +} + +/****************************************************************** + CreateFwRuleObject - CoCreate a firewall rule, and set the common set of properties which are shared + between port and application firewall rules + +********************************************************************/ +static HRESULT CreateFwRuleObject( + __in BSTR bstrName, + __in int iProfile, + __in_opt LPCWSTR wzRemoteAddresses, + __in LPCWSTR wzPort, + __in int iProtocol, + __in LPCWSTR wzDescription, + __in int iDirection, + __out INetFwRule** ppNetFwRule + ) +{ + HRESULT hr = S_OK; + BSTR bstrRemoteAddresses = NULL; + BSTR bstrPort = NULL; + BSTR bstrDescription = NULL; + INetFwRule* pNetFwRule = NULL; + *ppNetFwRule = NULL; + + // convert to BSTRs to make COM happy + bstrRemoteAddresses = ::SysAllocString(wzRemoteAddresses); + ExitOnNull(bstrRemoteAddresses, hr, E_OUTOFMEMORY, "failed SysAllocString for remote addresses"); + bstrPort = ::SysAllocString(wzPort); + ExitOnNull(bstrPort, hr, E_OUTOFMEMORY, "failed SysAllocString for port"); + bstrDescription = ::SysAllocString(wzDescription); + ExitOnNull(bstrDescription, hr, E_OUTOFMEMORY, "failed SysAllocString for description"); + + hr = ::CoCreateInstance(__uuidof(NetFwRule), NULL, CLSCTX_ALL, __uuidof(INetFwRule), (void**)&pNetFwRule); + ExitOnFailure(hr, "failed to create NetFwRule object"); + + hr = pNetFwRule->put_Name(bstrName); + ExitOnFailure(hr, "failed to set exception name"); + + hr = pNetFwRule->put_Profiles(static_cast(iProfile)); + ExitOnFailure(hr, "failed to set exception profile"); + + if (MSI_NULL_INTEGER != iProtocol) + { + hr = pNetFwRule->put_Protocol(static_cast(iProtocol)); + ExitOnFailure(hr, "failed to set exception protocol"); + } + + if (bstrPort && *bstrPort) + { + hr = pNetFwRule->put_LocalPorts(bstrPort); + ExitOnFailure(hr, "failed to set exception port"); + } + + if (bstrRemoteAddresses && *bstrRemoteAddresses) + { + hr = pNetFwRule->put_RemoteAddresses(bstrRemoteAddresses); + ExitOnFailure(hr, "failed to set exception remote addresses '%ls'", bstrRemoteAddresses); + } + + if (bstrDescription && *bstrDescription) + { + hr = pNetFwRule->put_Description(bstrDescription); + ExitOnFailure(hr, "failed to set exception description '%ls'", bstrDescription); + } + + if (MSI_NULL_INTEGER != iDirection) + { + hr = pNetFwRule->put_Direction(static_cast (iDirection)); + ExitOnFailure(hr, "failed to set exception direction"); + } + + *ppNetFwRule = pNetFwRule; + pNetFwRule = NULL; + +LExit: + ReleaseBSTR(bstrRemoteAddresses); + ReleaseBSTR(bstrPort); + ReleaseBSTR(bstrDescription); + ReleaseObject(pNetFwRule); + + return hr; +} + +/****************************************************************** + FSupportProfiles - Returns true if we support profiles on this machine. + (Only on Vista or later) + +********************************************************************/ +static BOOL FSupportProfiles() +{ + BOOL fSupportProfiles = FALSE; + INetFwRules* pNetFwRules = NULL; + + // We only support profiles if we can co-create an instance of NetFwPolicy2. + // This will not work on pre-vista machines. + if (SUCCEEDED(GetFirewallRules(TRUE, &pNetFwRules)) && pNetFwRules != NULL) + { + fSupportProfiles = TRUE; + ReleaseObject(pNetFwRules); + } + + return fSupportProfiles; +} + +/****************************************************************** + GetCurrentFirewallProfile - get the active firewall profile as an + INetFwProfile, which owns the lists of exceptions we're + updating. + +********************************************************************/ +static HRESULT GetCurrentFirewallProfile( + __in BOOL fIgnoreFailures, + __out INetFwProfile** ppfwProfile + ) +{ + HRESULT hr = S_OK; + INetFwMgr* pfwMgr = NULL; + INetFwPolicy* pfwPolicy = NULL; + INetFwProfile* pfwProfile = NULL; + *ppfwProfile = NULL; + + do + { + ReleaseNullObject(pfwPolicy); + ReleaseNullObject(pfwMgr); + ReleaseNullObject(pfwProfile); + + if (SUCCEEDED(hr = ::CoCreateInstance(__uuidof(NetFwMgr), NULL, CLSCTX_INPROC_SERVER, __uuidof(INetFwMgr), (void**)&pfwMgr)) && + SUCCEEDED(hr = pfwMgr->get_LocalPolicy(&pfwPolicy)) && + SUCCEEDED(hr = pfwPolicy->get_CurrentProfile(&pfwProfile))) + { + break; + } + else if (fIgnoreFailures) + { + ExitFunction1(hr = S_FALSE); + } + else + { + WcaLog(LOGMSG_STANDARD, "Failed to connect to Windows Firewall"); + UINT er = WcaErrorMessage(msierrFirewallCannotConnect, hr, INSTALLMESSAGE_ERROR | MB_ABORTRETRYIGNORE, 0); + switch (er) + { + case IDABORT: // exit with the current HRESULT + ExitFunction(); + case IDRETRY: // clean up and retry the loop + hr = S_FALSE; + break; + case IDIGNORE: // pass S_FALSE back to the caller, who knows how to ignore the failure + ExitFunction1(hr = S_FALSE); + default: // No UI, so default is to fail. + ExitFunction(); + } + } + } while (S_FALSE == hr); + + *ppfwProfile = pfwProfile; + pfwProfile = NULL; + +LExit: + ReleaseObject(pfwPolicy); + ReleaseObject(pfwMgr); + ReleaseObject(pfwProfile); + + return hr; +} + +/****************************************************************** + AddApplicationException + +********************************************************************/ +static HRESULT AddApplicationException( + __in LPCWSTR wzFile, + __in LPCWSTR wzName, + __in int iProfile, + __in_opt LPCWSTR wzRemoteAddresses, + __in BOOL fIgnoreFailures, + __in LPCWSTR wzPort, + __in int iProtocol, + __in LPCWSTR wzDescription, + __in int iDirection + ) +{ + HRESULT hr = S_OK; + BSTR bstrFile = NULL; + BSTR bstrName = NULL; + INetFwRules* pNetFwRules = NULL; + INetFwRule* pNetFwRule = NULL; + + // convert to BSTRs to make COM happy + bstrFile = ::SysAllocString(wzFile); + ExitOnNull(bstrFile, hr, E_OUTOFMEMORY, "failed SysAllocString for path"); + bstrName = ::SysAllocString(wzName); + ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "failed SysAllocString for name"); + + // get the collection of firewall rules + hr = GetFirewallRules(fIgnoreFailures, &pNetFwRules); + ExitOnFailure(hr, "failed to get firewall rules object"); + if (S_FALSE == hr) // user or package author chose to ignore missing firewall + { + ExitFunction(); + } + + // try to find it (i.e., support reinstall) + hr = pNetFwRules->Item(bstrName, &pNetFwRule); + if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) + { + hr = CreateFwRuleObject(bstrName, iProfile, wzRemoteAddresses, wzPort, iProtocol, wzDescription, iDirection, &pNetFwRule); + ExitOnFailure(hr, "failed to create FwRule object"); + + // set edge traversal to true + hr = pNetFwRule->put_EdgeTraversal(VARIANT_TRUE); + ExitOnFailure(hr, "failed to set application exception edgetraversal property"); + + // set path + hr = pNetFwRule->put_ApplicationName(bstrFile); + ExitOnFailure(hr, "failed to set application name"); + + // enable it + hr = pNetFwRule->put_Enabled(VARIANT_TRUE); + ExitOnFailure(hr, "failed to to enable application exception"); + + // add it to the list of authorized apps + hr = pNetFwRules->Add(pNetFwRule); + ExitOnFailure(hr, "failed to add app to the authorized apps list"); + } + else + { + // we found an existing app exception (if we succeeded, that is) + ExitOnFailure(hr, "failed trying to find existing app"); + + // enable it (just in case it was disabled) + pNetFwRule->put_Enabled(VARIANT_TRUE); + } + +LExit: + ReleaseBSTR(bstrName); + ReleaseBSTR(bstrFile); + ReleaseObject(pNetFwRules); + ReleaseObject(pNetFwRule); + + return fIgnoreFailures ? S_OK : hr; +} + +/****************************************************************** + AddApplicationExceptionOnCurrentProfile + +********************************************************************/ +static HRESULT AddApplicationExceptionOnCurrentProfile( + __in LPCWSTR wzFile, + __in LPCWSTR wzName, + __in_opt LPCWSTR wzRemoteAddresses, + __in BOOL fIgnoreFailures + ) +{ + HRESULT hr = S_OK; + BSTR bstrFile = NULL; + BSTR bstrName = NULL; + BSTR bstrRemoteAddresses = NULL; + INetFwProfile* pfwProfile = NULL; + INetFwAuthorizedApplications* pfwApps = NULL; + INetFwAuthorizedApplication* pfwApp = NULL; + + // convert to BSTRs to make COM happy + bstrFile = ::SysAllocString(wzFile); + ExitOnNull(bstrFile, hr, E_OUTOFMEMORY, "failed SysAllocString for path"); + bstrName = ::SysAllocString(wzName); + ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "failed SysAllocString for name"); + bstrRemoteAddresses = ::SysAllocString(wzRemoteAddresses); + ExitOnNull(bstrRemoteAddresses, hr, E_OUTOFMEMORY, "failed SysAllocString for remote addresses"); + + // get the firewall profile, which is our entry point for adding exceptions + hr = GetCurrentFirewallProfile(fIgnoreFailures, &pfwProfile); + ExitOnFailure(hr, "failed to get firewall profile"); + if (S_FALSE == hr) // user or package author chose to ignore missing firewall + { + ExitFunction(); + } + + // first, let's see if the app is already on the exception list + hr = pfwProfile->get_AuthorizedApplications(&pfwApps); + ExitOnFailure(hr, "failed to get list of authorized apps"); + + // try to find it (i.e., support reinstall) + hr = pfwApps->Item(bstrFile, &pfwApp); + if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) + { + // not found, so we get to add it + hr = ::CoCreateInstance(__uuidof(NetFwAuthorizedApplication), NULL, CLSCTX_INPROC_SERVER, __uuidof(INetFwAuthorizedApplication), reinterpret_cast(&pfwApp)); + ExitOnFailure(hr, "failed to create authorized app"); + + // set the display name + hr = pfwApp->put_Name(bstrName); + ExitOnFailure(hr, "failed to set authorized app name"); + + // set path + hr = pfwApp->put_ProcessImageFileName(bstrFile); + ExitOnFailure(hr, "failed to set authorized app path"); + + // set the allowed remote addresses + if (bstrRemoteAddresses && *bstrRemoteAddresses) + { + hr = pfwApp->put_RemoteAddresses(bstrRemoteAddresses); + ExitOnFailure(hr, "failed to set authorized app remote addresses"); + } + + // add it to the list of authorized apps + hr = pfwApps->Add(pfwApp); + ExitOnFailure(hr, "failed to add app to the authorized apps list"); + } + else + { + // we found an existing app exception (if we succeeded, that is) + ExitOnFailure(hr, "failed trying to find existing app"); + + // enable it (just in case it was disabled) + pfwApp->put_Enabled(VARIANT_TRUE); + } + +LExit: + ReleaseBSTR(bstrRemoteAddresses); + ReleaseBSTR(bstrName); + ReleaseBSTR(bstrFile); + ReleaseObject(pfwApp); + ReleaseObject(pfwApps); + ReleaseObject(pfwProfile); + + return fIgnoreFailures ? S_OK : hr; +} + +/****************************************************************** + AddPortException + +********************************************************************/ +static HRESULT AddPortException( + __in LPCWSTR wzName, + __in int iProfile, + __in_opt LPCWSTR wzRemoteAddresses, + __in BOOL fIgnoreFailures, + __in LPCWSTR wzPort, + __in int iProtocol, + __in LPCWSTR wzDescription, + __in int iDirection +) +{ + HRESULT hr = S_OK; + BSTR bstrName = NULL; + INetFwRules* pNetFwRules = NULL; + INetFwRule* pNetFwRule = NULL; + + // convert to BSTRs to make COM happy + bstrName = ::SysAllocString(wzName); + ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "failed SysAllocString for name"); + + // get the collection of firewall rules + hr = GetFirewallRules(fIgnoreFailures, &pNetFwRules); + ExitOnFailure(hr, "failed to get firewall rules object"); + if (S_FALSE == hr) // user or package author chose to ignore missing firewall + { + ExitFunction(); + } + + // try to find it (i.e., support reinstall) + hr = pNetFwRules->Item(bstrName, &pNetFwRule); + if (HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) == hr) + { + hr = CreateFwRuleObject(bstrName, iProfile, wzRemoteAddresses, wzPort, iProtocol, wzDescription, iDirection, &pNetFwRule); + ExitOnFailure(hr, "failed to create FwRule object"); + + // enable it + hr = pNetFwRule->put_Enabled(VARIANT_TRUE); + ExitOnFailure(hr, "failed to to enable port exception"); + + // add it to the list of authorized ports + hr = pNetFwRules->Add(pNetFwRule); + ExitOnFailure(hr, "failed to add app to the authorized ports list"); + } + else + { + // we found an existing port exception (if we succeeded, that is) + ExitOnFailure(hr, "failed trying to find existing port rule"); + + // enable it (just in case it was disabled) + pNetFwRule->put_Enabled(VARIANT_TRUE); + } + +LExit: + ReleaseBSTR(bstrName); + ReleaseObject(pNetFwRules); + ReleaseObject(pNetFwRule); + + return fIgnoreFailures ? S_OK : hr; +} + +/****************************************************************** + AddPortExceptionOnCurrentProfile + +********************************************************************/ +static HRESULT AddPortExceptionOnCurrentProfile( + __in LPCWSTR wzName, + __in_opt LPCWSTR wzRemoteAddresses, + __in BOOL fIgnoreFailures, + __in int iPort, + __in int iProtocol + ) +{ + HRESULT hr = S_OK; + BSTR bstrName = NULL; + BSTR bstrRemoteAddresses = NULL; + INetFwProfile* pfwProfile = NULL; + INetFwOpenPorts* pfwPorts = NULL; + INetFwOpenPort* pfwPort = NULL; + + // convert to BSTRs to make COM happy + bstrName = ::SysAllocString(wzName); + ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "failed SysAllocString for name"); + bstrRemoteAddresses = ::SysAllocString(wzRemoteAddresses); + ExitOnNull(bstrRemoteAddresses, hr, E_OUTOFMEMORY, "failed SysAllocString for remote addresses"); + + // create and initialize a new open port object + hr = ::CoCreateInstance(__uuidof(NetFwOpenPort), NULL, CLSCTX_INPROC_SERVER, __uuidof(INetFwOpenPort), reinterpret_cast(&pfwPort)); + ExitOnFailure(hr, "failed to create new open port"); + + hr = pfwPort->put_Port(iPort); + ExitOnFailure(hr, "failed to set exception port"); + + hr = pfwPort->put_Protocol(static_cast(iProtocol)); + ExitOnFailure(hr, "failed to set exception protocol"); + + if (bstrRemoteAddresses && *bstrRemoteAddresses) + { + hr = pfwPort->put_RemoteAddresses(bstrRemoteAddresses); + ExitOnFailure(hr, "failed to set exception remote addresses '%ls'", bstrRemoteAddresses); + } + + hr = pfwPort->put_Name(bstrName); + ExitOnFailure(hr, "failed to set exception name"); + + // get the firewall profile, its current list of open ports, and add ours + hr = GetCurrentFirewallProfile(fIgnoreFailures, &pfwProfile); + ExitOnFailure(hr, "failed to get firewall profile"); + if (S_FALSE == hr) // user or package author chose to ignore missing firewall + { + ExitFunction(); + } + + hr = pfwProfile->get_GloballyOpenPorts(&pfwPorts); + ExitOnFailure(hr, "failed to get open ports"); + + hr = pfwPorts->Add(pfwPort); + ExitOnFailure(hr, "failed to add exception to global list"); + +LExit: + ReleaseBSTR(bstrRemoteAddresses); + ReleaseBSTR(bstrName); + ReleaseObject(pfwProfile); + ReleaseObject(pfwPorts); + ReleaseObject(pfwPort); + + return fIgnoreFailures ? S_OK : hr; +} + +/****************************************************************** + RemoveException - Removes the exception rule with the given name. + +********************************************************************/ +static HRESULT RemoveException( + __in LPCWSTR wzName, + __in BOOL fIgnoreFailures + ) +{ + HRESULT hr = S_OK;; + INetFwRules* pNetFwRules = NULL; + + // convert to BSTRs to make COM happy + BSTR bstrName = ::SysAllocString(wzName); + ExitOnNull(bstrName, hr, E_OUTOFMEMORY, "failed SysAllocString for path"); + + // get the collection of firewall rules + hr = GetFirewallRules(fIgnoreFailures, &pNetFwRules); + ExitOnFailure(hr, "failed to get firewall rules object"); + if (S_FALSE == hr) // user or package author chose to ignore missing firewall + { + ExitFunction(); + } + + hr = pNetFwRules->Remove(bstrName); + ExitOnFailure(hr, "failed to remove authorized app"); + +LExit: + ReleaseBSTR(bstrName); + ReleaseObject(pNetFwRules); + + return fIgnoreFailures ? S_OK : hr; +} + +/****************************************************************** + RemoveApplicationExceptionFromCurrentProfile + +********************************************************************/ +static HRESULT RemoveApplicationExceptionFromCurrentProfile( + __in LPCWSTR wzFile, + __in BOOL fIgnoreFailures + ) +{ + HRESULT hr = S_OK; + INetFwProfile* pfwProfile = NULL; + INetFwAuthorizedApplications* pfwApps = NULL; + + // convert to BSTRs to make COM happy + BSTR bstrFile = ::SysAllocString(wzFile); + ExitOnNull(bstrFile, hr, E_OUTOFMEMORY, "failed SysAllocString for path"); + + // get the firewall profile, which is our entry point for removing exceptions + hr = GetCurrentFirewallProfile(fIgnoreFailures, &pfwProfile); + ExitOnFailure(hr, "failed to get firewall profile"); + if (S_FALSE == hr) // user or package author chose to ignore missing firewall + { + ExitFunction(); + } + + // now get the list of app exceptions and remove the one + hr = pfwProfile->get_AuthorizedApplications(&pfwApps); + ExitOnFailure(hr, "failed to get list of authorized apps"); + + hr = pfwApps->Remove(bstrFile); + ExitOnFailure(hr, "failed to remove authorized app"); + +LExit: + ReleaseBSTR(bstrFile); + ReleaseObject(pfwApps); + ReleaseObject(pfwProfile); + + return fIgnoreFailures ? S_OK : hr; +} + +/****************************************************************** + RemovePortExceptionFromCurrentProfile + +********************************************************************/ +static HRESULT RemovePortExceptionFromCurrentProfile( + __in int iPort, + __in int iProtocol, + __in BOOL fIgnoreFailures + ) +{ + HRESULT hr = S_OK; + INetFwProfile* pfwProfile = NULL; + INetFwOpenPorts* pfwPorts = NULL; + + // get the firewall profile, which is our entry point for adding exceptions + hr = GetCurrentFirewallProfile(fIgnoreFailures, &pfwProfile); + ExitOnFailure(hr, "failed to get firewall profile"); + if (S_FALSE == hr) // user or package author chose to ignore missing firewall + { + ExitFunction(); + } + + hr = pfwProfile->get_GloballyOpenPorts(&pfwPorts); + ExitOnFailure(hr, "failed to get open ports"); + + hr = pfwPorts->Remove(iPort, static_cast(iProtocol)); + ExitOnFailure(hr, "failed to remove open port %d, protocol %d", iPort, iProtocol); + +LExit: + return fIgnoreFailures ? S_OK : hr; +} + +static HRESULT AddApplicationException( + __in BOOL fSupportProfiles, + __in LPCWSTR wzFile, + __in LPCWSTR wzName, + __in int iProfile, + __in_opt LPCWSTR wzRemoteAddresses, + __in BOOL fIgnoreFailures, + __in LPCWSTR wzPort, + __in int iProtocol, + __in LPCWSTR wzDescription, + __in int iDirection +) +{ + HRESULT hr = S_OK; + + if (fSupportProfiles) + { + hr = AddApplicationException(wzFile, wzName, iProfile, wzRemoteAddresses, fIgnoreFailures, wzPort, iProtocol, wzDescription, iDirection); + } + else + { + if (0 != *wzPort || MSI_NULL_INTEGER != iProtocol) + { + // NOTE: This is treated as an error rather than either creating a rule based on just the application (no port), or + // just the port because it is unclear what is the proper fall back. For example, suppose that you have code that + // runs in dllhost.exe. Clearly falling back to opening all of dllhost is wrong. Because the firewall is a security + // feature, it seems better to require the MSI author to indicate the behavior that they want. + 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); + return fIgnoreFailures ? S_OK : E_NOTIMPL; + } + + hr = AddApplicationExceptionOnCurrentProfile(wzFile, wzName, wzRemoteAddresses, fIgnoreFailures); + } + + return hr; +} + +static HRESULT AddPortException( + __in BOOL fSupportProfiles, + __in LPCWSTR wzName, + __in int iProfile, + __in_opt LPCWSTR wzRemoteAddresses, + __in BOOL fIgnoreFailures, + __in LPCWSTR wzPort, + __in int iProtocol, + __in LPCWSTR wzDescription, + __in int iDirection +) +{ + HRESULT hr = S_OK; + + if (fSupportProfiles) + { + hr = AddPortException(wzName, iProfile, wzRemoteAddresses, fIgnoreFailures, wzPort, iProtocol, wzDescription, iDirection); + } + else + { + hr = AddPortExceptionOnCurrentProfile(wzName, wzRemoteAddresses, fIgnoreFailures, wcstol(wzPort, NULL, 10), iProtocol); + } + + return hr; +} + +static HRESULT RemoveApplicationException( + __in BOOL fSupportProfiles, + __in LPCWSTR wzName, + __in LPCWSTR wzFile, + __in BOOL fIgnoreFailures, + __in LPCWSTR wzPort, + __in int iProtocol + ) +{ + HRESULT hr = S_OK; + + if (fSupportProfiles) + { + hr = RemoveException(wzName, fIgnoreFailures); + } + else + { + if (0 != *wzPort || MSI_NULL_INTEGER != iProtocol) + { + 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); + return S_OK; + } + + hr = RemoveApplicationExceptionFromCurrentProfile(wzFile, fIgnoreFailures); + } + + return hr; +} + +static HRESULT RemovePortException( + __in BOOL fSupportProfiles, + __in LPCWSTR wzName, + __in LPCWSTR wzPort, + __in int iProtocol, + __in BOOL fIgnoreFailures + ) +{ + HRESULT hr = S_OK; + + if (fSupportProfiles) + { + hr = RemoveException(wzName, fIgnoreFailures); + } + else + { + hr = RemovePortExceptionFromCurrentProfile(wcstol(wzPort, NULL, 10), iProtocol, fIgnoreFailures); + } + + return hr; +} + +/****************************************************************** + ExecFirewallExceptions - deferred custom action entry point to + register and remove firewall exceptions. + +********************************************************************/ +extern "C" UINT __stdcall ExecFirewallExceptions( + __in MSIHANDLE hInstall + ) +{ + HRESULT hr = S_OK; + BOOL fSupportProfiles = FALSE; + LPWSTR pwz = NULL; + LPWSTR pwzCustomActionData = NULL; + int iTodo = WCA_TODO_UNKNOWN; + LPWSTR pwzName = NULL; + LPWSTR pwzRemoteAddresses = NULL; + int iAttributes = 0; + int iTarget = fetUnknown; + LPWSTR pwzFile = NULL; + LPWSTR pwzPort = NULL; + LPWSTR pwzDescription = NULL; + int iProtocol = 0; + int iProfile = 0; + int iDirection = 0; + + // initialize + hr = WcaInitialize(hInstall, "ExecFirewallExceptions"); + ExitOnFailure(hr, "failed to initialize"); + + hr = WcaGetProperty( L"CustomActionData", &pwzCustomActionData); + ExitOnFailure(hr, "failed to get CustomActionData"); + WcaLog(LOGMSG_TRACEONLY, "CustomActionData: %ls", pwzCustomActionData); + + hr = ::CoInitialize(NULL); + ExitOnFailure(hr, "failed to initialize COM"); + + // Find out if we support profiles (only on Vista or later) + fSupportProfiles = FSupportProfiles(); + + // loop through all the passed in data + pwz = pwzCustomActionData; + while (pwz && *pwz) + { + // extract the custom action data and if rolling back, swap INSTALL and UNINSTALL + hr = WcaReadIntegerFromCaData(&pwz, &iTodo); + ExitOnFailure(hr, "failed to read todo from custom action data"); + if (::MsiGetMode(hInstall, MSIRUNMODE_ROLLBACK)) + { + if (WCA_TODO_INSTALL == iTodo) + { + iTodo = WCA_TODO_UNINSTALL; + } + else if (WCA_TODO_UNINSTALL == iTodo) + { + iTodo = WCA_TODO_INSTALL; + } + } + + hr = WcaReadStringFromCaData(&pwz, &pwzName); + ExitOnFailure(hr, "failed to read name from custom action data"); + + hr = WcaReadIntegerFromCaData(&pwz, &iProfile); + ExitOnFailure(hr, "failed to read profile from custom action data"); + + hr = WcaReadStringFromCaData(&pwz, &pwzRemoteAddresses); + ExitOnFailure(hr, "failed to read remote addresses from custom action data"); + + hr = WcaReadIntegerFromCaData(&pwz, &iAttributes); + ExitOnFailure(hr, "failed to read attributes from custom action data"); + BOOL fIgnoreFailures = feaIgnoreFailures == (iAttributes & feaIgnoreFailures); + + hr = WcaReadIntegerFromCaData(&pwz, &iTarget); + ExitOnFailure(hr, "failed to read target from custom action data"); + + if (iTarget == fetApplication) + { + hr = WcaReadStringFromCaData(&pwz, &pwzFile); + ExitOnFailure(hr, "failed to read file path from custom action data"); + } + + hr = WcaReadStringFromCaData(&pwz, &pwzPort); + ExitOnFailure(hr, "failed to read port from custom action data"); + hr = WcaReadIntegerFromCaData(&pwz, &iProtocol); + ExitOnFailure(hr, "failed to read protocol from custom action data"); + hr = WcaReadStringFromCaData(&pwz, &pwzDescription); + ExitOnFailure(hr, "failed to read protocol from custom action data"); + hr = WcaReadIntegerFromCaData(&pwz, &iDirection); + ExitOnFailure(hr, "failed to read direction from custom action data"); + + switch (iTarget) + { + case fetPort: + switch (iTodo) + { + case WCA_TODO_INSTALL: + case WCA_TODO_REINSTALL: + WcaLog(LOGMSG_STANDARD, "Installing firewall exception2 %ls on port %ls, protocol %d", pwzName, pwzPort, iProtocol); + hr = AddPortException(fSupportProfiles, pwzName, iProfile, pwzRemoteAddresses, fIgnoreFailures, pwzPort, iProtocol, pwzDescription, iDirection); + ExitOnFailure(hr, "failed to add/update port exception for name '%ls' on port %ls, protocol %d", pwzName, pwzPort, iProtocol); + break; + + case WCA_TODO_UNINSTALL: + WcaLog(LOGMSG_STANDARD, "Uninstalling firewall exception2 %ls on port %ls, protocol %d", pwzName, pwzPort, iProtocol); + hr = RemovePortException(fSupportProfiles, pwzName, pwzPort, iProtocol, fIgnoreFailures); + ExitOnFailure(hr, "failed to remove port exception for name '%ls' on port %ls, protocol %d", pwzName, pwzPort, iProtocol); + break; + } + break; + + case fetApplication: + switch (iTodo) + { + case WCA_TODO_INSTALL: + case WCA_TODO_REINSTALL: + WcaLog(LOGMSG_STANDARD, "Installing firewall exception2 %ls (%ls)", pwzName, pwzFile); + hr = AddApplicationException(fSupportProfiles, pwzFile, pwzName, iProfile, pwzRemoteAddresses, fIgnoreFailures, pwzPort, iProtocol, pwzDescription, iDirection); + ExitOnFailure(hr, "failed to add/update application exception for name '%ls', file '%ls'", pwzName, pwzFile); + break; + + case WCA_TODO_UNINSTALL: + WcaLog(LOGMSG_STANDARD, "Uninstalling firewall exception2 %ls (%ls)", pwzName, pwzFile); + hr = RemoveApplicationException(fSupportProfiles, pwzName, pwzFile, fIgnoreFailures, pwzPort, iProtocol); + ExitOnFailure(hr, "failed to remove application exception for name '%ls', file '%ls'", pwzName, pwzFile); + break; + } + break; + } + } + +LExit: + ReleaseStr(pwzCustomActionData); + ReleaseStr(pwzName); + ReleaseStr(pwzRemoteAddresses); + ReleaseStr(pwzFile); + ReleaseStr(pwzPort); + ReleaseStr(pwzDescription); + ::CoUninitialize(); + + return WcaFinalize(FAILED(hr) ? ERROR_INSTALL_FAILURE : ERROR_SUCCESS); +} 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 @@ +; 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. + + +LIBRARY "fwca" + +EXPORTS + SchedFirewallExceptionsInstall + SchedFirewallExceptionsUninstall + 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 @@ + + + True + + \ 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 @@ + + + + + + + + + + Debug + ARM64 + + + Release + ARM64 + + + + Debug + X64 + + + Release + X64 + + + + Debug + Win32 + + + Release + Win32 + + + + + {F72D34CA-48DA-4DFD-91A9-A0C78BEF6981} + DynamicLibrary + fwca + v142 + Unicode + fwca.def + WiX Toolset Firewall CustomAction + + + + + + + msi.lib + + + + + Create + + + + + + + + + + + + + + + + + + + + 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}. + + + + + 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 @@ + + + + + \ 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 @@ +#pragma once +// 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. + + +#include +#include +#include +#include +#include + +#include "wcautil.h" +#include "fileutil.h" +#include "pathutil.h" +#include "strutil.h" + +#include "CustomMsiErrors.h" +#include "cost.h" + +#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 @@ + + + + + + + + + + + + + + + + + + \ 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 @@ +// 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. + +namespace WixToolsetTest.Firewall +{ + using System.Linq; + using WixBuildTools.TestSupport; + using WixToolset.Core.TestPackage; + using WixToolset.Firewall; + using Xunit; + + public class FirewallExtensionFixture + { + [Fact] + public void CanBuildUsingFirewall() + { + var folder = TestData.Get(@"TestData\UsingFirewall"); + var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder }); + + var results = build.BuildAndQuery(Build, "Wix4FirewallException", "CustomAction"); + Assert.Equal(new[] + { + "CustomAction:Wix4ExecFirewallExceptionsInstall_X86\t3073\tWix4FWCA_X86\tExecFirewallExceptions\t", + "CustomAction:Wix4ExecFirewallExceptionsUninstall_X86\t3073\tWix4FWCA_X86\tExecFirewallExceptions\t", + "CustomAction:Wix4RollbackFirewallExceptionsInstall_X86\t3329\tWix4FWCA_X86\tExecFirewallExceptions\t", + "CustomAction:Wix4RollbackFirewallExceptionsUninstall_X86\t3329\tWix4FWCA_X86\tExecFirewallExceptions\t", + "CustomAction:Wix4SchedFirewallExceptionsInstall_X86\t1\tWix4FWCA_X86\tSchedFirewallExceptionsInstall\t", + "CustomAction:Wix4SchedFirewallExceptionsUninstall_X86\t1\tWix4FWCA_X86\tSchedFirewallExceptionsUninstall\t", + "Wix4FirewallException:ExampleFirewall\texample\t*\t42\t6\t\t0\t2147483647\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\tAn example firewall\t1", + }, results); + } + + [Fact] + public void CanBuildUsingFirewallARM64() + { + var folder = TestData.Get(@"TestData\UsingFirewall"); + var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder }); + + var results = build.BuildAndQuery(BuildARM64, "Wix4FirewallException", "CustomAction"); + Assert.Equal(new[] + { + "CustomAction:Wix4ExecFirewallExceptionsInstall_A64\t3073\tWix4FWCA_A64\tExecFirewallExceptions\t", + "CustomAction:Wix4ExecFirewallExceptionsUninstall_A64\t3073\tWix4FWCA_A64\tExecFirewallExceptions\t", + "CustomAction:Wix4RollbackFirewallExceptionsInstall_A64\t3329\tWix4FWCA_A64\tExecFirewallExceptions\t", + "CustomAction:Wix4RollbackFirewallExceptionsUninstall_A64\t3329\tWix4FWCA_A64\tExecFirewallExceptions\t", + "CustomAction:Wix4SchedFirewallExceptionsInstall_A64\t1\tWix4FWCA_A64\tSchedFirewallExceptionsInstall\t", + "CustomAction:Wix4SchedFirewallExceptionsUninstall_A64\t1\tWix4FWCA_A64\tSchedFirewallExceptionsUninstall\t", + "Wix4FirewallException:ExampleFirewall\texample\t*\t42\t6\t\t0\t2147483647\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\tAn example firewall\t1", + }, results); + } + + [Fact] + public void CanBuildUsingOutboundFirewall() + { + var folder = TestData.Get(@"TestData\UsingOutboundFirewall"); + var build = new Builder(folder, typeof(FirewallExtensionFactory), new[] { folder }); + + var results = build.BuildAndQuery(Build, "Wix4FirewallException"); + Assert.Equal(new[] + { + "Wix4FirewallException:fex.5c8b_4C0THcQTvn8tpwhoRrgck\texample\t*\t42\t6\t\t0\t2147483647\tfilF5_pLhBuF5b4N9XEo52g_hUM5Lo\tAn example outbound firewall\t2", + }, results); + } + + private static void Build(string[] args) + { + var result = WixRunner.Execute(args); + result.AssertSuccess(); + } + + private static void BuildARM64(string[] args) + { + var newArgs = args.ToList(); + newArgs.Add("-platform"); + newArgs.Add("arm64"); + + var result = WixRunner.Execute(newArgs.ToArray()); + result.AssertSuccess(); + } + } +} 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 @@ + + + + + + A newer version of [ProductName] is already installed. + MsiPackage + + 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 @@ + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + 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 @@ + + + + + + A newer version of [ProductName] is already installed. + MsiPackage + + 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 @@ + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + 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 @@ + + + + + + netcoreapp3.1 + false + + + + NU1701 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + True + + \ 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 Binary files /dev/null and b/src/ext/Firewall/wix.snk 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 @@ +// 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. + +namespace WixToolset.Firewall +{ + using System; + using System.Collections.Generic; + using System.Xml.Linq; + using WixToolset.Data; + using WixToolset.Extensibility; + using WixToolset.Extensibility.Data; + using WixToolset.Firewall.Symbols; + + /// + /// The compiler for the WiX Toolset Firewall Extension. + /// + public sealed class FirewallCompiler : BaseCompilerExtension + { + public override XNamespace Namespace => "http://wixtoolset.org/schemas/v4/wxs/firewall"; + + /// + /// Processes an element for the Compiler. + /// + /// Source line number for the parent element. + /// Parent element of element to process. + /// Element to process. + /// Extra information about the context in which this element is being parsed. + public override void ParseElement(Intermediate intermediate, IntermediateSection section, XElement parentElement, XElement element, IDictionary context) + { + switch (parentElement.Name.LocalName) + { + case "File": + var fileId = context["FileId"]; + var fileComponentId = context["ComponentId"]; + + switch (element.Name.LocalName) + { + case "FirewallException": + this.ParseFirewallExceptionElement(intermediate, section, element, fileComponentId, fileId); + break; + default: + this.ParseHelper.UnexpectedElement(parentElement, element); + break; + } + break; + case "Component": + var componentId = context["ComponentId"]; + + switch (element.Name.LocalName) + { + case "FirewallException": + this.ParseFirewallExceptionElement(intermediate, section, element, componentId, null); + break; + default: + this.ParseHelper.UnexpectedElement(parentElement, element); + break; + } + break; + default: + this.ParseHelper.UnexpectedElement(parentElement, element); + break; + } + } + + /// + /// Parses a FirewallException element. + /// + /// The element to parse. + /// Identifier of the component that owns this firewall exception. + /// The file identifier of the parent element (null if nested under Component). + private void ParseFirewallExceptionElement(Intermediate intermediate, IntermediateSection section, XElement element, string componentId, string fileId) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + Identifier id = null; + string name = null; + int attributes = 0; + string file = null; + string program = null; + string port = null; + int? protocol = null; + int? profile = null; + string scope = null; + string remoteAddresses = null; + string description = null; + int? direction = null; + + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Id": + id = this.ParseHelper.GetAttributeIdentifier(sourceLineNumbers, attrib); + break; + case "Name": + name = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "File": + if (null != fileId) + { + this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, "File", "File")); + } + else + { + file = this.ParseHelper.GetAttributeIdentifierValue(sourceLineNumbers, attrib); + } + break; + case "IgnoreFailure": + if (YesNoType.Yes == this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib)) + { + attributes |= 0x1; // feaIgnoreFailures + } + break; + case "Program": + if (null != fileId) + { + this.Messaging.Write(ErrorMessages.IllegalAttributeWhenNested(sourceLineNumbers, element.Name.LocalName, "Program", "File")); + } + else + { + program = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + } + break; + case "Port": + port = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Protocol": + var protocolValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + switch (protocolValue) + { + case "tcp": + protocol = FirewallConstants.NET_FW_IP_PROTOCOL_TCP; + break; + case "udp": + protocol = FirewallConstants.NET_FW_IP_PROTOCOL_UDP; + break; + default: + this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Protocol", protocolValue, "tcp", "udp")); + break; + } + break; + case "Scope": + scope = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + switch (scope) + { + case "any": + remoteAddresses = "*"; + break; + case "localSubnet": + remoteAddresses = "LocalSubnet"; + break; + default: + this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Scope", scope, "any", "localSubnet")); + break; + } + break; + case "Profile": + var profileValue = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + switch (profileValue) + { + case "domain": + profile = FirewallConstants.NET_FW_PROFILE2_DOMAIN; + break; + case "private": + profile = FirewallConstants.NET_FW_PROFILE2_PRIVATE; + break; + case "public": + profile = FirewallConstants.NET_FW_PROFILE2_PUBLIC; + break; + case "all": + profile = FirewallConstants.NET_FW_PROFILE2_ALL; + break; + default: + this.Messaging.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, element.Name.LocalName, "Profile", profileValue, "domain", "private", "public", "all")); + break; + } + break; + case "Description": + description = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + case "Outbound": + direction = this.ParseHelper.GetAttributeYesNoValue(sourceLineNumbers, attrib) == YesNoType.Yes + ? FirewallConstants.NET_FW_RULE_DIR_OUT + : FirewallConstants.NET_FW_RULE_DIR_IN; + break; + default: + this.ParseHelper.UnexpectedAttribute(element, attrib); + break; + } + } + else + { + this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); + } + } + + // parse RemoteAddress children + foreach (var child in element.Elements()) + { + if (this.Namespace == child.Name.Namespace) + { + switch (child.Name.LocalName) + { + case "RemoteAddress": + if (null != scope) + { + this.Messaging.Write(FirewallErrors.IllegalRemoteAddressWithScopeAttribute(sourceLineNumbers)); + } + else + { + this.ParseRemoteAddressElement(intermediate, section, child, ref remoteAddresses); + } + break; + default: + this.ParseHelper.UnexpectedElement(element, child); + break; + } + } + else + { + this.ParseHelper.ParseExtensionElement(this.Context.Extensions, intermediate, section, element, child); + } + } + + if (null == id) + { + id = this.ParseHelper.CreateIdentifier("fex", name, remoteAddresses, componentId); + } + + // Name is required + if (null == name) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Name")); + } + + // Scope or child RemoteAddress(es) are required + if (null == remoteAddresses) + { + this.Messaging.Write(ErrorMessages.ExpectedAttributeOrElement(sourceLineNumbers, element.Name.LocalName, "Scope", "RemoteAddress")); + } + + // can't have both Program and File + if (null != program && null != file) + { + this.Messaging.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, element.Name.LocalName, "File", "Program")); + } + + // must be nested under File, have File or Program attributes, or have Port attribute + if (String.IsNullOrEmpty(fileId) && String.IsNullOrEmpty(file) && String.IsNullOrEmpty(program) && String.IsNullOrEmpty(port)) + { + this.Messaging.Write(FirewallErrors.NoExceptionSpecified(sourceLineNumbers)); + } + + if (!this.Messaging.EncounteredError) + { + // at this point, File attribute and File parent element are treated the same + if (null != file) + { + fileId = file; + } + + var symbol = section.AddSymbol(new WixFirewallExceptionSymbol(sourceLineNumbers, id) + { + Name = name, + RemoteAddresses = remoteAddresses, + Profile = profile ?? FirewallConstants.NET_FW_PROFILE2_ALL, + ComponentRef = componentId, + Description = description, + Direction = direction ?? FirewallConstants.NET_FW_RULE_DIR_IN, + }); + + if (!String.IsNullOrEmpty(port)) + { + symbol.Port = port; + + if (!protocol.HasValue) + { + // default protocol is "TCP" + protocol = FirewallConstants.NET_FW_IP_PROTOCOL_TCP; + } + } + + if (protocol.HasValue) + { + symbol.Protocol = protocol.Value; + } + + if (!String.IsNullOrEmpty(fileId)) + { + symbol.Program = $"[#{fileId}]"; + this.ParseHelper.CreateSimpleReference(section, sourceLineNumbers, SymbolDefinitions.File, fileId); + } + else if (!String.IsNullOrEmpty(program)) + { + symbol.Program = program; + } + + if (CompilerConstants.IntegerNotSet != attributes) + { + symbol.Attributes = attributes; + } + + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedFirewallExceptionsInstall", this.Context.Platform, CustomActionPlatforms.ARM64 | CustomActionPlatforms.X64 | CustomActionPlatforms.X86); + this.ParseHelper.CreateCustomActionReference(sourceLineNumbers, section, "Wix4SchedFirewallExceptionsUninstall", this.Context.Platform, CustomActionPlatforms.ARM64 | CustomActionPlatforms.X64 | CustomActionPlatforms.X86); + } + } + + /// + /// Parses a RemoteAddress element + /// + /// The element to parse. + private void ParseRemoteAddressElement(Intermediate intermediate, IntermediateSection section, XElement element, ref string remoteAddresses) + { + var sourceLineNumbers = this.ParseHelper.GetSourceLineNumbers(element); + string address = null; + + // no attributes + foreach (var attrib in element.Attributes()) + { + if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || this.Namespace == attrib.Name.Namespace) + { + switch (attrib.Name.LocalName) + { + case "Value": + address = this.ParseHelper.GetAttributeValue(sourceLineNumbers, attrib); + break; + } + } + else + { + this.ParseHelper.ParseExtensionAttribute(this.Context.Extensions, intermediate, section, element, attrib); + } + } + + this.ParseHelper.ParseForExtensionElements(this.Context.Extensions, intermediate, section, element); + + if (String.IsNullOrEmpty(address)) + { + this.Messaging.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, element.Name.LocalName, "Value")); + } + else + { + if (String.IsNullOrEmpty(remoteAddresses)) + { + remoteAddresses = address; + } + else + { + remoteAddresses = String.Concat(remoteAddresses, ",", address); + } + } + } + } +} 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 @@ +// 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. + +namespace WixToolset.Firewall +{ + using System; + using System.Collections.Generic; + using System.Text; + + static class FirewallConstants + { + // from icftypes.h + public const int NET_FW_RULE_DIR_IN = 1; + public const int NET_FW_RULE_DIR_OUT = 2; + public const int NET_FW_IP_PROTOCOL_TCP = 6; + public const int NET_FW_IP_PROTOCOL_UDP = 17; + + // from icftypes.h + public const int NET_FW_PROFILE2_DOMAIN = 0x0001; + public const int NET_FW_PROFILE2_PRIVATE = 0x0002; + public const int NET_FW_PROFILE2_PUBLIC = 0x0004; + public const int NET_FW_PROFILE2_ALL = 0x7FFFFFFF; + } +} 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 @@ +// 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. + +namespace WixToolset.Firewall +{ +#if TODO_CONSIDER_DECOMPILER + using System; + using System.Collections; + using System.Diagnostics; + using System.Globalization; + using WixToolset.Data; + using WixToolset.Extensibility; + using Firewall = WixToolset.Extensions.Serialize.Firewall; + using Wix = WixToolset.Data.Serialize; + + /// + /// The decompiler for the WiX Toolset Firewall Extension. + /// + public sealed class FirewallDecompiler : DecompilerExtension + { + /// + /// Creates a decompiler for Firewall Extension. + /// + public FirewallDecompiler() + { + this.TableDefinitions = FirewallExtensionData.GetExtensionTableDefinitions(); + } + + /// + /// Get the extensions library to be removed. + /// + /// Table definitions for library. + /// Library to remove from decompiled output. + public override Library GetLibraryToRemove(TableDefinitionCollection tableDefinitions) + { + return FirewallExtensionData.GetExtensionLibrary(tableDefinitions); + } + + /// + /// Decompiles an extension table. + /// + /// The table to decompile. + public override void DecompileTable(Table table) + { + switch (table.Name) + { + case "WixFirewallException": + this.DecompileWixFirewallExceptionTable(table); + break; + default: + base.DecompileTable(table); + break; + } + } + + /// + /// Decompile the WixFirewallException table. + /// + /// The table to decompile. + private void DecompileWixFirewallExceptionTable(Table table) + { + foreach (Row row in table.Rows) + { + Firewall.FirewallException fire = new Firewall.FirewallException(); + fire.Id = (string)row[0]; + fire.Name = (string)row[1]; + + string[] addresses = ((string)row[2]).Split(','); + if (1 == addresses.Length) + { + // special-case the Scope attribute values + if ("*" == addresses[0]) + { + fire.Scope = Firewall.FirewallException.ScopeType.any; + } + else if ("LocalSubnet" == addresses[0]) + { + fire.Scope = Firewall.FirewallException.ScopeType.localSubnet; + } + else + { + FirewallDecompiler.AddRemoteAddress(fire, addresses[0]); + } + } + else + { + foreach (string address in addresses) + { + FirewallDecompiler.AddRemoteAddress(fire, address); + } + } + + if (!row.IsColumnEmpty(3)) + { + fire.Port = (string)row[3]; + } + + if (!row.IsColumnEmpty(4)) + { + switch (Convert.ToInt32(row[4])) + { + case FirewallConstants.NET_FW_IP_PROTOCOL_TCP: + fire.Protocol = Firewall.FirewallException.ProtocolType.tcp; + break; + case FirewallConstants.NET_FW_IP_PROTOCOL_UDP: + fire.Protocol = Firewall.FirewallException.ProtocolType.udp; + break; + } + } + + if (!row.IsColumnEmpty(5)) + { + fire.Program = (string)row[5]; + } + + if (!row.IsColumnEmpty(6)) + { + int attr = Convert.ToInt32(row[6]); + if (0x1 == (attr & 0x1)) // feaIgnoreFailures + { + fire.IgnoreFailure = Firewall.YesNoType.yes; + } + } + + if (!row.IsColumnEmpty(7)) + { + switch (Convert.ToInt32(row[7])) + { + case FirewallConstants.NET_FW_PROFILE2_DOMAIN: + fire.Profile = Firewall.FirewallException.ProfileType.domain; + break; + case FirewallConstants.NET_FW_PROFILE2_PRIVATE: + fire.Profile = Firewall.FirewallException.ProfileType.@private; + break; + case FirewallConstants.NET_FW_PROFILE2_PUBLIC: + fire.Profile = Firewall.FirewallException.ProfileType.@public; + break; + case FirewallConstants.NET_FW_PROFILE2_ALL: + fire.Profile = Firewall.FirewallException.ProfileType.all; + break; + } + } + + // Description column is new in v3.6 + if (9 < row.Fields.Length && !row.IsColumnEmpty(9)) + { + fire.Description = (string)row[9]; + } + + if (!row.IsColumnEmpty(10)) + { + switch (Convert.ToInt32(row[10])) + { + case FirewallConstants.NET_FW_RULE_DIR_IN: + fire.Direction = Firewall.FirewallException.DirectionType.@in; + break; + case FirewallConstants.NET_FW_RULE_DIR_OUT: + fire.Direction = Firewall.FirewallException.DirectionType.@out; + break; + } + } + + Wix.Component component = (Wix.Component)this.Core.GetIndexedElement("Component", (string)row[8]); + if (null != component) + { + component.AddChild(fire); + } + else + { + this.Core.OnMessage(WixWarnings.ExpectedForeignRow(row.SourceLineNumbers, table.Name, row.GetPrimaryKey(DecompilerConstants.PrimaryKeyDelimiter), "Component_", (string)row[6], "Component")); + } + } + } + + private static void AddRemoteAddress(Firewall.FirewallException fire, string address) + { + Firewall.RemoteAddress remote = new Firewall.RemoteAddress(); + remote.Content = address; + fire.AddChild(remote); + } + } +#endif +} 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 @@ +// 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. + +namespace WixToolset.Firewall +{ + using System.Resources; + using WixToolset.Data; + + public static class FirewallErrors + { + public static Message IllegalRemoteAddressWithScopeAttribute(SourceLineNumber sourceLineNumbers) + { + 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."); + } + + public static Message NoExceptionSpecified(SourceLineNumber sourceLineNumbers) + { + 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."); + } + + private static Message Message(SourceLineNumber sourceLineNumber, Ids id, string format, params object[] args) + { + return new Message(sourceLineNumber, MessageLevel.Error, (int)id, format, args); + } + + private static Message Message(SourceLineNumber sourceLineNumber, Ids id, ResourceManager resourceManager, string resourceName, params object[] args) + { + return new Message(sourceLineNumber, MessageLevel.Error, (int)id, resourceManager, resourceName, args); + } + + public enum Ids + { + IllegalRemoteAddressWithScopeAttribute = 6401, + NoExceptionSpecified = 6403, + } + } +} 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 @@ +// 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. + +namespace WixToolset.Firewall +{ + using WixToolset.Data; + using WixToolset.Extensibility; + + public sealed class FirewallExtensionData : BaseExtensionData + { + public override string DefaultCulture => "en-US"; + + public override bool TryGetSymbolDefinitionByName(string name, out IntermediateSymbolDefinition symbolDefinition) + { + symbolDefinition = FirewallSymbolDefinitions.ByName(name); + return symbolDefinition != null; + } + + public override Intermediate GetLibrary(ISymbolDefinitionCreator symbolDefinitions) + { + return Intermediate.Load(typeof(FirewallExtensionData).Assembly, "WixToolset.Firewall.firewall.wixlib", symbolDefinitions); + } + } +} 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 @@ +// 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. + +namespace WixToolset.Firewall +{ + using System; + using System.Collections.Generic; + using WixToolset.Extensibility; + + public class FirewallExtensionFactory : BaseExtensionFactory + { + protected override IReadOnlyCollection ExtensionTypes => new[] + { + typeof(FirewallCompiler), + typeof(FirewallExtensionData), + typeof(FirewallWindowsInstallerBackendBinderExtension), + }; + } +} 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 @@ +// 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. + +namespace WixToolset.Firewall +{ + using WixToolset.Data.WindowsInstaller; + + public static class FirewallTableDefinitions + { + public static readonly TableDefinition WixFirewallException = new TableDefinition( + "Wix4FirewallException", + FirewallSymbolDefinitions.WixFirewallException, + new[] + { + new ColumnDefinition("Wix4FirewallException", ColumnType.String, 72, primaryKey: true, nullable: false, ColumnCategory.Identifier, description: "The primary key, a non-localized token.", modularizeType: ColumnModularizeType.Column), + new ColumnDefinition("Name", ColumnType.Localized, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Localizable display name.", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("RemoteAddresses", ColumnType.String, 0, primaryKey: false, nullable: false, ColumnCategory.Formatted, description: "Remote address to accept incoming connections from.", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("Port", ColumnType.String, 0, primaryKey: false, nullable: true, ColumnCategory.Formatted, minValue: 1, description: "Port number.", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("Protocol", ColumnType.Number, 1, primaryKey: false, nullable: true, ColumnCategory.Integer, minValue: 6, maxValue: 17, description: "Protocol (6=TCP; 17=UDP)."), + new ColumnDefinition("Program", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Exception for a program (formatted path name).", modularizeType: ColumnModularizeType.Property), + new ColumnDefinition("Attributes", ColumnType.Number, 4, primaryKey: false, nullable: true, ColumnCategory.Unknown, description: "Vital=1"), + 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)."), + 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), + new ColumnDefinition("Description", ColumnType.String, 255, primaryKey: false, nullable: true, ColumnCategory.Formatted, description: "Description displayed in Windows Firewall manager for this firewall rule."), + new ColumnDefinition("Direction", ColumnType.Number, 1, primaryKey: false, nullable: true, ColumnCategory.Integer, minValue: 1, maxValue: 2, description: "Direction (1=in; 2=out)"), + }, + symbolIdIsPrimaryKey: true + ); + + public static readonly TableDefinition[] All = new[] + { + WixFirewallException, + }; + } +} 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 @@ +// 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. + +namespace WixToolset.Firewall +{ + using System.Collections.Generic; + using WixToolset.Data.WindowsInstaller; + using WixToolset.Extensibility; + + public class FirewallWindowsInstallerBackendBinderExtension : BaseWindowsInstallerBackendBinderExtension + { + public override IReadOnlyCollection TableDefinitions => FirewallTableDefinitions.All; + } +} 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 @@ +// 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. + +namespace WixToolset.Firewall +{ + using System; + using WixToolset.Data; + + public enum FirewallSymbolDefinitionType + { + WixFirewallException, + } + + public static partial class FirewallSymbolDefinitions + { + public static readonly Version Version = new Version("4.0.0"); + + public static IntermediateSymbolDefinition ByName(string name) + { + if (!Enum.TryParse(name, out FirewallSymbolDefinitionType type)) + { + return null; + } + + return ByType(type); + } + + public static IntermediateSymbolDefinition ByType(FirewallSymbolDefinitionType type) + { + switch (type) + { + case FirewallSymbolDefinitionType.WixFirewallException: + return FirewallSymbolDefinitions.WixFirewallException; + + default: + throw new ArgumentOutOfRangeException(nameof(type)); + } + } + } +} 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 @@ +// 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. + +namespace WixToolset.Firewall +{ + using WixToolset.Data; + using WixToolset.Firewall.Symbols; + + public static partial class FirewallSymbolDefinitions + { + public static readonly IntermediateSymbolDefinition WixFirewallException = new IntermediateSymbolDefinition( + FirewallSymbolDefinitionType.WixFirewallException.ToString(), + new[] + { + new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Name), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.RemoteAddresses), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Port), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Protocol), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Program), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Attributes), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Profile), IntermediateFieldType.Number), + new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.ComponentRef), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Description), IntermediateFieldType.String), + new IntermediateFieldDefinition(nameof(WixFirewallExceptionSymbolFields.Direction), IntermediateFieldType.Number), + }, + typeof(WixFirewallExceptionSymbol)); + } +} + +namespace WixToolset.Firewall.Symbols +{ + using WixToolset.Data; + + public enum WixFirewallExceptionSymbolFields + { + Name, + RemoteAddresses, + Port, + Protocol, + Program, + Attributes, + Profile, + ComponentRef, + Description, + Direction, + } + + public class WixFirewallExceptionSymbol : IntermediateSymbol + { + public WixFirewallExceptionSymbol() : base(FirewallSymbolDefinitions.WixFirewallException, null, null) + { + } + + public WixFirewallExceptionSymbol(SourceLineNumber sourceLineNumber, Identifier id = null) : base(FirewallSymbolDefinitions.WixFirewallException, sourceLineNumber, id) + { + } + + public IntermediateField this[WixFirewallExceptionSymbolFields index] => this.Fields[(int)index]; + + public string Name + { + get => this.Fields[(int)WixFirewallExceptionSymbolFields.Name].AsString(); + set => this.Set((int)WixFirewallExceptionSymbolFields.Name, value); + } + + public string RemoteAddresses + { + get => this.Fields[(int)WixFirewallExceptionSymbolFields.RemoteAddresses].AsString(); + set => this.Set((int)WixFirewallExceptionSymbolFields.RemoteAddresses, value); + } + + public string Port + { + get => this.Fields[(int)WixFirewallExceptionSymbolFields.Port].AsString(); + set => this.Set((int)WixFirewallExceptionSymbolFields.Port, value); + } + + public int? Protocol + { + get => this.Fields[(int)WixFirewallExceptionSymbolFields.Protocol].AsNullableNumber(); + set => this.Set((int)WixFirewallExceptionSymbolFields.Protocol, value); + } + + public string Program + { + get => this.Fields[(int)WixFirewallExceptionSymbolFields.Program].AsString(); + set => this.Set((int)WixFirewallExceptionSymbolFields.Program, value); + } + + public int Attributes + { + get => this.Fields[(int)WixFirewallExceptionSymbolFields.Attributes].AsNumber(); + set => this.Set((int)WixFirewallExceptionSymbolFields.Attributes, value); + } + + public int Profile + { + get => this.Fields[(int)WixFirewallExceptionSymbolFields.Profile].AsNumber(); + set => this.Set((int)WixFirewallExceptionSymbolFields.Profile, value); + } + + public string ComponentRef + { + get => this.Fields[(int)WixFirewallExceptionSymbolFields.ComponentRef].AsString(); + set => this.Set((int)WixFirewallExceptionSymbolFields.ComponentRef, value); + } + + public string Description + { + get => this.Fields[(int)WixFirewallExceptionSymbolFields.Description].AsString(); + set => this.Set((int)WixFirewallExceptionSymbolFields.Description, value); + } + + public int Direction + { + get => this.Fields[(int)WixFirewallExceptionSymbolFields.Direction].AsNumber(); + set => this.Set((int)WixFirewallExceptionSymbolFields.Direction, value); + } + } +} \ 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 @@ + + + + + + netstandard2.0 + WixToolset.Firewall + WiX Toolset Firewallity Extension + WiX Toolset Firewall Extension + true + build + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + $(MSBuildThisFileDirectory)..\tools\WixToolset.Firewall.wixext.dll + + + + + 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 @@ + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + 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 @@ + + + + + + + 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 @@ + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 @@ + + + + + Cannot connect to Windows Firewall. ([2] [3] [4] [5]) + + Configuring Windows Firewall + Configuring Windows Firewall + Rolling back Windows Firewall configuration + Installing Windows Firewall configuration + Rolling back Windows Firewall configuration + Uninstalling Windows Firewall configuration + 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 @@ + + + + No se puede conectar al Firewall de Windows. ([2] [3] [4] [5]) + + Configurando el Firewall de Windows + Configurando el Firewall de Windows + Regresando la configuración del Firewall de Windows + Instalando la configuración del Firewall de Windows + Regresando la configuración del Firewall de Windows + Desinstalando la configuración del Firewall de Windows + 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 @@ + + + True + + \ 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 @@ + + + + + Library + true + en-us + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + Windows ファイアウォールへ接続できません。 ([2] [3] [4] [5]) + + Windows ファイアウォールを構成しています + Windows ファイアウォールを構成しています + Windows ファイアウォール構成をロールバックしています + Windows ファイアウォール構成をインストールしています + Windows ファイアウォール構成をロールバックしています + Windows ファイアウォール構成をアンインストールしています + 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 @@ + + + + + Nie udało się połączyć z Zaporą systemu Windows. ([2] [3] [4] [5]) + + Dodawanie wyjątków do Zapory systemu Windows + Usuwanie wyjątków z Zapory systemu Windows + Cofanie zmian konfiguracji Zapory systemu Windows + Konfigurowywanie Zapory systemu Windows + Cofanie zmian konfiguracji Zapory systemu Windows + Konfigurowywanie Zapory systemu Windows + diff --git a/src/ext/global.json b/src/ext/global.json new file mode 100644 index 00000000..23dd3fa6 --- /dev/null +++ b/src/ext/global.json @@ -0,0 +1,5 @@ +{ + "msbuild-sdks": { + "WixToolset.Sdk": "4.0.0-build-0211" + } +} -- cgit v1.2.3-55-g6feb