::value_t> ReadEnums(const Registry::Key& policiesKey)
+ {
+ using Mapping = details::ValuePolicyMapping;
+
+ auto enumKey = policiesKey.SubKey(Mapping::KeyName);
+ if (!enumKey.has_value())
+ {
+ return std::nullopt;
+ }
+
+ typename Mapping::value_t map;
+ for (const auto& value : enumKey->Values())
+ {
+ std::optional potentialValue = value.Value();
+
+ if (potentialValue)
+ {
+ auto entry = Mapping::ReadAndValidateItem(value);
+ if (entry.has_value())
+ {
+ map.insert(*entry);
+ }
+ else
+ {
+ AICLI_LOG(Core, Warning, << "Failed to read Group Policy enum value. Policy [" << Mapping::KeyName << "], Value [" << value.Name() << ']');
+ }
+ }
+ else
+ {
+ AICLI_LOG(Core, Verbose, << "Group Policy enum value not found. Policy [" << Mapping::KeyName << "], Value [" << value.Name() << ']');
+ }
+ }
+
+ return map;
+ }
+
// Reads a list from a Group Policy.
// The list is stored in a sub-key of the policies key, and each value in that key is a list item.
// Cases not considered by this function because we don't use them:
@@ -255,9 +293,16 @@ namespace AppInstaller::Settings
return ReadList<_policy_>(policiesKey); \
}
+#define POLICY_MAPPING_DEFAULT_ENUM_READ(_policy_) \
+ std::optional::value_t> ValuePolicyMapping<_policy_>::ReadAndValidate(const Registry::Key& policiesKey) \
+ { \
+ return ReadEnums<_policy_>(policiesKey); \
+ }
+
POLICY_MAPPING_DEFAULT_LIST_READ(ValuePolicy::AdditionalSources);
POLICY_MAPPING_DEFAULT_LIST_READ(ValuePolicy::AllowedSources);
POLICY_MAPPING_DEFAULT_READ(ValuePolicy::DefaultProxy);
+ POLICY_MAPPING_DEFAULT_ENUM_READ(ValuePolicy::AllowedSecurityZones);
std::nullopt_t ValuePolicyMapping::ReadAndValidate(const Registry::Key&)
{
@@ -292,6 +337,27 @@ namespace AppInstaller::Settings
{
return ReadSourceFromRegistryValue(item);
}
+
+ std::optional> ValuePolicyMapping::ReadAndValidateItem(const Registry::ValueList::ValueRef& entry)
+ {
+#define CONFIGURATION_ALLOWED_ZONES_READ(_zone_) \
+ if (entry.Name() == #_zone_) \
+ { \
+ auto data = entry.Value()->TryGetValue(); \
+ auto value = data.value_or(true); \
+ return std::make_pair(SecurityZoneOptions::_zone_, value); \
+ }
+
+ CONFIGURATION_ALLOWED_ZONES_READ(LocalMachine);
+ CONFIGURATION_ALLOWED_ZONES_READ(Intranet);
+ CONFIGURATION_ALLOWED_ZONES_READ(TrustedSites);
+ CONFIGURATION_ALLOWED_ZONES_READ(Internet);
+ CONFIGURATION_ALLOWED_ZONES_READ(UntrustedSites);
+#undef CONFIGURATION_ALLOWED_ZONES_READ
+
+ AICLI_LOG(Core, Warning, << "Unknown value in WindowsPackageManagerAllowedSecurityZones: " << entry.Name());
+ return std::nullopt;
+ }
}
TogglePolicy TogglePolicy::GetPolicy(TogglePolicy::Policy policy)
@@ -326,6 +392,10 @@ namespace AppInstaller::Settings
return TogglePolicy(policy, "EnableWindowsPackageManagerConfiguration"sv, String::PolicyEnableWinGetConfiguration);
case TogglePolicy::Policy::ProxyCommandLineOptions:
return TogglePolicy(policy, "EnableWindowsPackageManagerProxyCommandLineOptions"sv, String::PolicyEnableProxyCommandLineOptions);
+ case TogglePolicy::Policy::AllowedSecurityZones:
+ return TogglePolicy(policy, "EnableWindowsPackageManagerAllowedSecurityZones"sv, String::PolicyEnableAllowedSecurityZones);
+ case TogglePolicy::Policy::SmartScreenCheck:
+ return TogglePolicy(policy, "EnableWindowsPackageManagerSmartScreenCheck"sv, String::PolicyEnableSmartScreenValidation);
default:
THROW_HR(E_UNEXPECTED);
}
diff --git a/src/AppInstallerSharedLib/Public/AppInstallerErrors.h b/src/AppInstallerSharedLib/Public/AppInstallerErrors.h
index d00bc8a18a..463d2f2ae1 100644
--- a/src/AppInstallerSharedLib/Public/AppInstallerErrors.h
+++ b/src/AppInstallerSharedLib/Public/AppInstallerErrors.h
@@ -152,6 +152,7 @@
#define APPINSTALLER_CLI_ERROR_SFSCLIENT_PACKAGE_NOT_SUPPORTED ((HRESULT)0x8A150084)
#define APPINSTALLER_CLI_ERROR_LICENSING_API_FAILED_FORBIDDEN ((HRESULT)0x8A150085)
#define APPINSTALLER_CLI_ERROR_INSTALLER_ZERO_BYTE_FILE ((HRESULT)0x8A150086)
+#define APPINSTALLER_CLI_ERROR_BLOCKED_BY_REPUTATION_SERVICE ((HRESULT)0x8A150087)
// Install errors.
#define APPINSTALLER_CLI_ERROR_INSTALL_PACKAGE_IN_USE ((HRESULT)0x8A150101)
diff --git a/src/AppInstallerSharedLib/Public/winget/GroupPolicy.h b/src/AppInstallerSharedLib/Public/winget/GroupPolicy.h
index 850526f60c..d91bab156a 100644
--- a/src/AppInstallerSharedLib/Public/winget/GroupPolicy.h
+++ b/src/AppInstallerSharedLib/Public/winget/GroupPolicy.h
@@ -23,9 +23,20 @@ namespace AppInstaller::Settings
AdditionalSources,
AllowedSources,
DefaultProxy,
+ AllowedSecurityZones,
Max,
};
+ // Enum for the configurable security zones
+ enum class SecurityZoneOptions : DWORD
+ {
+ LocalMachine = 0,
+ Intranet = 1,
+ TrustedSites = 2,
+ Internet = 3,
+ UntrustedSites = 4,
+ };
+
// A policy that acts as a toggle to enable or disable a feature.
// They are backed by a DWORD value with values 0 and 1.
struct TogglePolicy
@@ -47,6 +58,8 @@ namespace AppInstaller::Settings
WinGetCommandLineInterfaces,
Configuration,
ProxyCommandLineOptions,
+ AllowedSecurityZones,
+ SmartScreenCheck,
Max,
};
@@ -113,6 +126,12 @@ namespace AppInstaller::Settings
// item_t - Type of each item
// KeyName -- Name of the sub-key containing the list
// ReadAndValidateItem() - Function that reads a single item from a subkey
+
+ // For enums:
+ // KeyName - Name of the sub-key containing the enums
+ // _mapTypeKey_ - Type of the key in the map
+ // _mapTypeValue_ - Type of the value in the map
+ // _mapTypeName_ - Name of the map type
};
template<>
@@ -149,11 +168,20 @@ namespace AppInstaller::Settings
static std::optional ReadAndValidateItem(const Registry::Value& item); \
)
+#define POLICY_MAPPING_ENUM_SPECIALIZATION(_policy_, _mapTypeName_, _mapTypeKey_, _mapTypeValue_, _keyName_) \
+ typedef std::map<_mapTypeKey_, _mapTypeValue_> _mapTypeName_; \
+ POLICY_MAPPING_SPECIALIZATION(_policy_, _mapTypeName_, \
+ static constexpr std::string_view KeyName = _keyName_; \
+ static std::optional ReadAndValidateItem(const Registry::ValueList::ValueRef& item); \
+ )
+
POLICY_MAPPING_VALUE_SPECIALIZATION(ValuePolicy::SourceAutoUpdateIntervalInMinutes, uint32_t, "SourceAutoUpdateInterval"sv, Registry::Value::Type::DWord);
POLICY_MAPPING_VALUE_SPECIALIZATION(ValuePolicy::DefaultProxy, std::string, "DefaultProxy"sv, Registry::Value::Type::String);
POLICY_MAPPING_LIST_SPECIALIZATION(ValuePolicy::AdditionalSources, SourceFromPolicy, "AdditionalSources"sv);
POLICY_MAPPING_LIST_SPECIALIZATION(ValuePolicy::AllowedSources, SourceFromPolicy, "AllowedSources"sv);
+
+ POLICY_MAPPING_ENUM_SPECIALIZATION(ValuePolicy::AllowedSecurityZones, SecurityZoneMap_t, SecurityZoneOptions, bool, "WindowsPackageManagerAllowedSecurityZones"sv);
}
// Representation of the policies read from the registry.
diff --git a/src/AppInstallerSharedLib/Public/winget/Resources.h b/src/AppInstallerSharedLib/Public/winget/Resources.h
index dc6591abd0..081e30f33f 100644
--- a/src/AppInstallerSharedLib/Public/winget/Resources.h
+++ b/src/AppInstallerSharedLib/Public/winget/Resources.h
@@ -60,6 +60,8 @@ namespace AppInstaller
WINGET_DEFINE_RESOURCE_STRINGID(PolicyEnableWindowsPackageManagerCommandLineInterfaces);
WINGET_DEFINE_RESOURCE_STRINGID(PolicyEnableWinGetConfiguration);
WINGET_DEFINE_RESOURCE_STRINGID(PolicyEnableProxyCommandLineOptions);
+ WINGET_DEFINE_RESOURCE_STRINGID(PolicyEnableAllowedSecurityZones);
+ WINGET_DEFINE_RESOURCE_STRINGID(PolicyEnableSmartScreenValidation);
WINGET_DEFINE_RESOURCE_STRINGID(SettingsWarningInvalidFieldFormat);
WINGET_DEFINE_RESOURCE_STRINGID(SettingsWarningInvalidFieldValue);
diff --git a/src/Internal/UriValidation/.gitignore b/src/Internal/UriValidation/.gitignore
new file mode 100644
index 0000000000..a19a3d9a13
--- /dev/null
+++ b/src/Internal/UriValidation/.gitignore
@@ -0,0 +1,4 @@
+# The following files are injected in the pipeline build
+packages.config
+UriValidation.props
+UriValidation_internal.cpp
\ No newline at end of file
diff --git a/src/Internal/UriValidation/UriValidation.cpp b/src/Internal/UriValidation/UriValidation.cpp
new file mode 100644
index 0000000000..8599606f88
--- /dev/null
+++ b/src/Internal/UriValidation/UriValidation.cpp
@@ -0,0 +1,34 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+#include "UriValidation.h"
+
+namespace AppInstaller::UriValidation
+{
+ namespace
+ {
+ bool EndsWith(const std::string& value, const std::string& ending)
+ {
+ if (ending.size() > value.size())
+ {
+ return false;
+ }
+
+ return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
+ }
+ }
+
+ UriValidationResult ValidateUri(const std::string& uri)
+ {
+#ifndef AICLI_DISABLE_TEST_HOOKS
+ // For testing purposes, block all URIs that end with "/block"
+ if (EndsWith(uri, "/block"))
+ {
+ return UriValidationResult(UriValidationDecision::Block, std::string());
+ }
+#endif
+
+ // In Dev mode, allow all URIs
+ return UriValidationResult(UriValidationDecision::Allow, std::string());
+ }
+}
diff --git a/src/Internal/UriValidation/UriValidation.h b/src/Internal/UriValidation/UriValidation.h
new file mode 100644
index 0000000000..b8676c4450
--- /dev/null
+++ b/src/Internal/UriValidation/UriValidation.h
@@ -0,0 +1,34 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+#pragma once
+
+#include
+
+namespace AppInstaller::UriValidation
+{
+ // The decision made based on the Uri validation.
+ enum class UriValidationDecision
+ {
+ Allow,
+ Block,
+ };
+
+ // The result of a Uri validation.
+ class UriValidationResult
+ {
+ public:
+ UriValidationResult(UriValidationDecision decision) : m_decision(decision), m_feedback(std::string()) {}
+ UriValidationResult(UriValidationDecision decision, std::string feedback) : m_decision(decision), m_feedback(feedback) {}
+ UriValidationDecision Decision() const { return m_decision; }
+ std::string Feedback() const { return m_feedback; }
+ private:
+ // The decision made based on the Uri validation.
+ UriValidationDecision m_decision;
+
+ // Uri to give feedback to smart screen about the decision.
+ std::string m_feedback;
+ };
+
+ // Validate the given Uri.
+ UriValidationResult ValidateUri(const std::string& uri);
+}
diff --git a/src/Internal/UriValidation/UriValidation.vcxproj b/src/Internal/UriValidation/UriValidation.vcxproj
new file mode 100644
index 0000000000..48cfe3d68c
--- /dev/null
+++ b/src/Internal/UriValidation/UriValidation.vcxproj
@@ -0,0 +1,414 @@
+
+
+
+
+
+ true
+ true
+ true
+ 15.0
+ {98920ab6-27b0-4c0f-b336-fa49de57a1ba}
+ Win32Proj
+ UriValidation
+ 10.0.22621.0
+ 10.0.17763.0
+ true
+ true
+
+
+
+
+ Debug
+ ARM
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Fuzzing
+ x64
+
+
+ Fuzzing
+ Win32
+
+
+ ReleaseStatic
+ ARM
+
+
+ ReleaseStatic
+ ARM64
+
+
+ ReleaseStatic
+ Win32
+
+
+ ReleaseStatic
+ x64
+
+
+ Release
+ ARM
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ StaticLibrary
+ v140
+ v141
+ v142
+ v143
+ Unicode
+
+
+ true
+ true
+
+
+ false
+ true
+ false
+
+
+ false
+ true
+ false
+
+
+ false
+ false
+ false
+ true
+
+
+ Spectre
+
+
+ Spectre
+
+
+ Spectre
+
+
+ Spectre
+
+
+ Spectre
+
+
+ Spectre
+
+
+ Spectre
+
+
+ Spectre
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\
+ true
+ true
+ ..\..\CodeAnalysis.ruleset
+
+
+ true
+ $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\
+ true
+ true
+ ..\..\CodeAnalysis.ruleset
+
+
+ true
+ $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\
+ true
+ true
+ ..\..\CodeAnalysis.ruleset
+
+
+ true
+ $(SolutionDir)x86\$(Configuration)\$(ProjectName)\
+ true
+ true
+ ..\..\CodeAnalysis.ruleset
+
+
+ false
+ $(SolutionDir)x86\$(Configuration)\$(ProjectName)\
+ true
+ false
+ ..\..\CodeAnalysis.ruleset
+
+
+ false
+ $(SolutionDir)x86\$(Configuration)\$(ProjectName)\
+ true
+ false
+ ..\..\CodeAnalysis.ruleset
+
+
+ false
+ $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\
+ true
+ false
+ ..\..\CodeAnalysis.ruleset
+
+
+ false
+ $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\
+ true
+ false
+ ..\..\CodeAnalysis.ruleset
+
+
+ false
+ $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\
+
+
+ false
+ $(SolutionDir)x86\$(Configuration)\$(ProjectName)\
+
+
+ false
+ $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\
+ true
+ false
+ ..\..\CodeAnalysis.ruleset
+
+
+ false
+ $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\
+ true
+ false
+ ..\..\CodeAnalysis.ruleset
+
+
+ false
+ $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\
+ true
+ false
+ ..\..\CodeAnalysis.ruleset
+
+
+ false
+ $(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\
+ true
+ false
+ ..\..\CodeAnalysis.ruleset
+
+
+
+ NotUsing
+ _CONSOLE;%(PreprocessorDefinitions)
+ Level4
+ %(AdditionalOptions) /permissive- /D _SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING
+
+
+
+
+ Disabled
+ _NO_ASYNCRTIMP;_SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING;_DEBUG;%(PreprocessorDefinitions);CLICOREDLLBUILD
+ $(ProjectDir);$(ProjectDir)..\..\AppInstallerSharedLib;$(ProjectDir)..\..\AppInstallerSharedLib\Public;%(AdditionalIncludeDirectories)
+ $(ProjectDir);$(ProjectDir)..\..\AppInstallerSharedLib;$(ProjectDir)..\..\AppInstallerSharedLib\Public;%(AdditionalIncludeDirectories)
+ $(ProjectDir);$(ProjectDir)..\..\AppInstallerSharedLib;$(ProjectDir)..\..\AppInstallerSharedLib\Public;%(AdditionalIncludeDirectories)
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ false
+ false
+ false
+
+
+ false
+ Windows
+ Windows
+ Windows
+
+
+
+
+ _NO_ASYNCRTIMP;_SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING;WIN32;%(PreprocessorDefinitions);CLICOREDLLBUILD
+ $(ProjectDir);$(ProjectDir)..\..\AppInstallerSharedLib;$(ProjectDir)..\..\AppInstallerSharedLib\Public;%(AdditionalIncludeDirectories)
+ true
+ true
+ true
+ false
+
+
+ Windows
+
+
+
+
+ MaxSpeed
+ true
+ true
+ _NO_ASYNCRTIMP;_SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING;NDEBUG;%(PreprocessorDefinitions);CLICOREDLLBUILD
+ $(ProjectDir);$(ProjectDir)..\..\AppInstallerSharedLib;$(ProjectDir)..\..\AppInstallerSharedLib\Public;%(AdditionalIncludeDirectories)
+ $(ProjectDir);$(ProjectDir)..\..\AppInstallerSharedLib;$(ProjectDir)..\..\AppInstallerSharedLib\Public;%(AdditionalIncludeDirectories)
+ $(ProjectDir);$(ProjectDir)..\..\AppInstallerSharedLib;$(ProjectDir)..\..\AppInstallerSharedLib\Public;%(AdditionalIncludeDirectories)
+ $(ProjectDir);$(ProjectDir)..\..\AppInstallerSharedLib;$(ProjectDir)..\..\AppInstallerSharedLib\Public;%(AdditionalIncludeDirectories)
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+
+
+ true
+ true
+ false
+ Windows
+ Windows
+ Windows
+ Windows
+
+
+
+
+ MaxSpeed
+ true
+ true
+ _NO_ASYNCRTIMP;_SILENCE_STDEXT_ARR_ITERS_DEPRECATION_WARNING;NDEBUG;%(PreprocessorDefinitions);CLICOREDLLBUILD
+ $(ProjectDir);$(ProjectDir)..\..\AppInstallerSharedLib;$(ProjectDir)..\..\AppInstallerSharedLib\Public;%(AdditionalIncludeDirectories)
+ $(ProjectDir);$(ProjectDir)..\..\AppInstallerSharedLib;$(ProjectDir)..\..\AppInstallerSharedLib\Public;%(AdditionalIncludeDirectories)
+ $(ProjectDir);$(ProjectDir)..\..\AppInstallerSharedLib;$(ProjectDir)..\..\AppInstallerSharedLib\Public;%(AdditionalIncludeDirectories)
+ $(ProjectDir);$(ProjectDir)..\..\AppInstallerSharedLib;$(ProjectDir)..\..\AppInstallerSharedLib\Public;%(AdditionalIncludeDirectories)
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ false
+ false
+ false
+ false
+ MultiThreaded
+ MultiThreaded
+ MultiThreaded
+ MultiThreaded
+ false
+ false
+ false
+ false
+
+
+ true
+ true
+ false
+ Windows
+ Windows
+ Windows
+ Windows
+
+
+
+
+ MaxSpeed
+ true
+ true
+ _NO_ASYNCRTIMP;NDEBUG;%(PreprocessorDefinitions);CLICOREDLLBUILD;WINGET_DISABLE_FOR_FUZZING;_DISABLE_VECTOR_ANNOTATION;_DISABLE_STRING_ANNOTATION
+ $(ProjectDir);$(ProjectDir)..\..\AppInstallerSharedLib;$(ProjectDir)..\..\AppInstallerSharedLib\Public;%(AdditionalIncludeDirectories)
+ true
+ stdcpp17
+ MultiThreaded
+ %(AdditionalOptions) /fsanitize=address /fsanitize-coverage=inline-8bit-counters /fsanitize-coverage=edge /fsanitize-coverage=trace-cmp /fsanitize-coverage=trace-div
+ false
+
+
+ true
+ true
+ false
+ Windows
+
+
+
+
+ AICLI_DISABLE_TEST_HOOKS;%(PreprocessorDefinitions)
+
+
+
+
+ WINGET_DISABLE_EXPERIMENTAL_FEATURES;%(PreprocessorDefinitions)
+
+
+
+
+ WINGET_ENABLE_RELEASE_BUILD;%(PreprocessorDefinitions)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 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}.
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Internal/UriValidation/UriValidation.vcxproj.filters b/src/Internal/UriValidation/UriValidation.vcxproj.filters
new file mode 100644
index 0000000000..01ce4a95da
--- /dev/null
+++ b/src/Internal/UriValidation/UriValidation.vcxproj.filters
@@ -0,0 +1,36 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Header Files
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/WindowsPackageManager/WindowsPackageManager.vcxproj b/src/WindowsPackageManager/WindowsPackageManager.vcxproj
index 510d07aa61..c2f46098e8 100644
--- a/src/WindowsPackageManager/WindowsPackageManager.vcxproj
+++ b/src/WindowsPackageManager/WindowsPackageManager.vcxproj
@@ -17,6 +17,7 @@
.
+
@@ -219,7 +220,8 @@
true
false
$(ProjectDir)..\vcpkg_installed
-
+
+
x64-release-static
@@ -519,6 +521,9 @@
{866c3f06-636f-4be8-bc24-5f86ecc606a1}
+
+ {98920ab6-27b0-4c0f-b336-fa49de57a1ba}
+
{82b39fda-e86b-4713-a873-9d56de00247a}
@@ -551,4 +556,4 @@
-
+
\ No newline at end of file