diff --git a/doc/Settings.md b/doc/Settings.md
index fcd14080b0..628cabcb52 100644
--- a/doc/Settings.md
+++ b/doc/Settings.md
@@ -312,3 +312,14 @@ You can enable the feature as shown below.
"configuration03": true
},
```
+
+### proxy
+
+This feature enables the use of web proxies.
+You can enable the feature as shown below.
+
+```json
+ "experimentalFeatures": {
+ "proxy": true
+ },
+```
diff --git a/doc/admx/DesktopAppInstaller.admx b/doc/admx/DesktopAppInstaller.admx
index 64b911e1f2..9cad850345 100644
--- a/doc/admx/DesktopAppInstaller.admx
+++ b/doc/admx/DesktopAppInstaller.admx
@@ -166,5 +166,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/admx/en-US/DesktopAppInstaller.adml b/doc/admx/en-US/DesktopAppInstaller.adml
index 4e80a38093..5c3142ab6b 100644
--- a/doc/admx/en-US/DesktopAppInstaller.adml
+++ b/doc/admx/en-US/DesktopAppInstaller.adml
@@ -100,7 +100,7 @@ If you disable or do not configure this setting, users will not be able to insta
If you disable this policy, users will not be able execute the Windows Package Manager CLI, and PowerShell cmdlets.
- If you enable, or do not configuring this policy, users will be able to execute the Windows Package Manager CLI commands, and PowerShell cmdlets. (Provided “Enable App Installer” policy is not disabled).
+ If you enable, or do not configure this policy, users will be able to execute the Windows Package Manager CLI commands, and PowerShell cmdlets. (Provided “Enable App Installer” policy is not disabled).
This policy does not override the “Enable App Installer” policy.
Enable Windows Package Manager Configuration
@@ -109,6 +109,19 @@ If you disable or do not configure this setting, users will not be able to insta
If you enable or do not configure this setting, users will be able to use the Windows Package Manager configuration feature.
If you disable this setting, users will not be able to use the Windows Package Manager configuration feature.
+ Enable Windows Package Manager Proxy command line options
+
+ This policy controls whether the Windows Package Manager usage of proxy can be configured by users through the command line.
+
+ If you enable this setting, users will be able to configure the Windows Package Manager's use of proxy through the command line.
+
+ If you disable or do not configure this setting, users will not be able to to configure the Windows Package Manager's use of proxy through the command line.
+ Set Windows Package Manager Default Proxy
+ This policy controls the default proxy used by the Windows Package Manager.
+
+If you disable or do not configure this setting, no proxy will be used by default.
+
+If you enable this setting, the specified proxy will be used by default.
@@ -120,6 +133,11 @@ If you disable this setting, users will not be able to use the Windows Package M
Allowed Sources:
+
+
+
+
+
diff --git a/schemas/JSON/settings/settings.export.schema.0.1.json b/schemas/JSON/settings/settings.export.schema.0.1.json
index 17d0e8d5e4..f8809255f5 100644
--- a/schemas/JSON/settings/settings.export.schema.0.1.json
+++ b/schemas/JSON/settings/settings.export.schema.0.1.json
@@ -16,8 +16,26 @@
"description": "Enable installing local manifests.",
"type": "boolean",
"default": false
+ },
+ "InstallerHashOverride": {
+ "description": "Enable overriding installer hash validation.",
+ "type": "boolean",
+ "default": false
+ },
+ "LocalArchiveMalwareScanOverride": {
+ "description": "Enable overriding malware scan for local archives.",
+ "type": "boolean",
+ "default": false
+ },
+ "ProxyCommandLineOptions": {
+ "description": "Enable using command line options for proxy.",
+ "type": "boolean",
+ "default": false
+ },
+ "DefaultProxy": {
+ "description": "Default proxy.",
+ "type": "string"
}
- }
},
"UserSettingsFile": {
"description": "Path for the winget's user settings file.",
diff --git a/schemas/JSON/settings/settings.schema.0.2.json b/schemas/JSON/settings/settings.schema.0.2.json
index 3a35440415..80e224487b 100644
--- a/schemas/JSON/settings/settings.schema.0.2.json
+++ b/schemas/JSON/settings/settings.schema.0.2.json
@@ -266,8 +266,13 @@
"type": "boolean",
"default": false
},
- "configuration": {
- "description": "Enable support for configuration",
+ "configuration03": {
+ "description": "Enable support for configuration schema 0.3",
+ "type": "boolean",
+ "default": false
+ },
+ "proxy": {
+ "description": "Enable support for proxies",
"type": "boolean",
"default": false
}
diff --git a/src/AppInstallerCLICore/Argument.cpp b/src/AppInstallerCLICore/Argument.cpp
index 7497468840..6299beb909 100644
--- a/src/AppInstallerCLICore/Argument.cpp
+++ b/src/AppInstallerCLICore/Argument.cpp
@@ -151,6 +151,10 @@ namespace AppInstaller::CLI
return { type, "enable"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::EnableDisable };
case Execution::Args::Type::AdminSettingDisable:
return { type, "disable"_liv, ArgTypeCategory::None, ArgTypeExclusiveSet::EnableDisable };
+ case Execution::Args::Type::SettingName:
+ return { type, "setting"_liv };
+ case Execution::Args::Type::SettingValue:
+ return { type, "value"_liv };
// Upgrade command
case Execution::Args::Type::All:
@@ -233,6 +237,11 @@ namespace AppInstaller::CLI
case Execution::Args::Type::AcceptSourceAgreements:
return { type, "accept-source-agreements"_liv, ArgTypeCategory::ExtendedSource };
+ case Execution::Args::Type::Proxy:
+ return { type, "proxy"_liv, ArgTypeCategory::CopyValueToSubContext, ArgTypeExclusiveSet::Proxy };
+ case Execution::Args::Type::NoProxy:
+ return { type, "no-proxy"_liv, ArgTypeCategory::CopyFlagToSubContext, ArgTypeExclusiveSet::Proxy };
+
case Execution::Args::Type::ToolVersion:
return { type, "version"_liv, 'v' };
@@ -268,7 +277,7 @@ namespace AppInstaller::CLI
case Args::Type::MultiQuery:
return Argument{ type, Resource::String::MultiQueryArgumentDescription, ArgumentType::Positional }.SetCountLimit(128);
case Args::Type::Manifest:
- return Argument{ type, Resource::String::ManifestArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help, Settings::TogglePolicy::Policy::LocalManifestFiles, Settings::AdminSetting::LocalManifestFiles };
+ return Argument{ type, Resource::String::ManifestArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help, Settings::TogglePolicy::Policy::LocalManifestFiles, Settings::BoolAdminSetting::LocalManifestFiles };
case Args::Type::Id:
return Argument{ type, Resource::String::IdArgumentDescription, ArgumentType::Standard, Argument::Visibility::Help };
case Args::Type::Name:
@@ -308,7 +317,7 @@ namespace AppInstaller::CLI
case Args::Type::InstallLocation:
return Argument{ type, Resource::String::LocationArgumentDescription, ArgumentType::Standard };
case Args::Type::HashOverride:
- return Argument{ type, Resource::String::HashOverrideArgumentDescription, ArgumentType::Flag, Settings::TogglePolicy::Policy::HashOverride, Settings::AdminSetting::InstallerHashOverride };
+ return Argument{ type, Resource::String::HashOverrideArgumentDescription, ArgumentType::Flag, Settings::TogglePolicy::Policy::HashOverride, Settings::BoolAdminSetting::InstallerHashOverride };
case Args::Type::AcceptPackageAgreements:
return Argument{ type, Resource::String::AcceptPackageAgreementsArgumentDescription, ArgumentType::Flag };
case Args::Type::NoUpgrade:
@@ -324,7 +333,7 @@ namespace AppInstaller::CLI
case Args::Type::SkipDependencies:
return Argument{ type, Resource::String::SkipDependenciesArgumentDescription, ArgumentType::Flag, false };
case Args::Type::IgnoreLocalArchiveMalwareScan:
- return Argument{ type, Resource::String::IgnoreLocalArchiveMalwareScanArgumentDescription, ArgumentType::Flag, Settings::TogglePolicy::Policy::LocalArchiveMalwareScanOverride, Settings::AdminSetting::LocalArchiveMalwareScanOverride };
+ return Argument{ type, Resource::String::IgnoreLocalArchiveMalwareScanArgumentDescription, ArgumentType::Flag, Settings::TogglePolicy::Policy::LocalArchiveMalwareScanOverride, Settings::BoolAdminSetting::LocalArchiveMalwareScanOverride };
case Args::Type::SourceName:
return Argument{ type, Resource::String::SourceNameArgumentDescription, ArgumentType::Positional, false };
case Args::Type::SourceArg:
@@ -379,6 +388,10 @@ namespace AppInstaller::CLI
return Argument{ type, Resource::String::AllowRebootArgumentDescription, ArgumentType::Flag };
case Args::Type::IgnoreResumeLimit:
return Argument{ type, Resource::String::IgnoreResumeLimitArgumentDescription, ArgumentType::Flag, ExperimentalFeature::Feature::Resume };
+ case Args::Type::Proxy:
+ return Argument{ type, Resource::String::ProxyArgumentDescription, ArgumentType::Standard, ExperimentalFeature::Feature::Proxy, TogglePolicy::Policy::ProxyCommandLineOptions, BoolAdminSetting::ProxyCommandLineOptions };
+ case Args::Type::NoProxy:
+ return Argument{ type, Resource::String::NoProxyArgumentDescription, ArgumentType::Flag, ExperimentalFeature::Feature::Proxy, TogglePolicy::Policy::ProxyCommandLineOptions, BoolAdminSetting::ProxyCommandLineOptions };
default:
THROW_HR(E_UNEXPECTED);
}
@@ -394,6 +407,8 @@ namespace AppInstaller::CLI
args.push_back(ForType(Args::Type::RetroStyle));
args.push_back(ForType(Args::Type::VerboseLogs));
args.emplace_back(Args::Type::DisableInteractivity, Resource::String::DisableInteractivityArgumentDescription, ArgumentType::Flag, false);
+ args.push_back(ForType(Args::Type::Proxy));
+ args.push_back(ForType(Args::Type::NoProxy));
}
std::string Argument::GetUsageString() const
diff --git a/src/AppInstallerCLICore/Argument.h b/src/AppInstallerCLICore/Argument.h
index d33741eaf1..741c2de068 100644
--- a/src/AppInstallerCLICore/Argument.h
+++ b/src/AppInstallerCLICore/Argument.h
@@ -85,6 +85,7 @@ namespace AppInstaller::CLI
PurgePreserve = 0x4,
PinType = 0x8,
StubType = 0x10,
+ Proxy = 0x20,
// This must always be at the end
Max
@@ -211,7 +212,7 @@ namespace AppInstaller::CLI
Argument::Visibility GetVisibility() const;
Settings::ExperimentalFeature::Feature Feature() const { return m_feature; }
Settings::TogglePolicy::Policy GroupPolicy() const { return m_groupPolicy; }
- Settings::AdminSetting AdminSetting() const { return m_adminSetting; }
+ Settings::BoolAdminSetting AdminSetting() const { return m_adminSetting; }
Argument& SetRequired(bool required) { m_required = required; return *this; }
Argument& SetCountLimit(size_t countLimit) { m_countLimit = countLimit; return *this; }
@@ -237,12 +238,15 @@ namespace AppInstaller::CLI
Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Argument::Visibility visibility, bool required, Settings::ExperimentalFeature::Feature feature) :
m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_type(type), m_visibility(visibility), m_required(required), m_feature(feature) {}
- Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Settings::TogglePolicy::Policy groupPolicy, Settings::AdminSetting adminSetting) :
+ Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Settings::TogglePolicy::Policy groupPolicy, Settings::BoolAdminSetting adminSetting) :
m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_type(type), m_groupPolicy(groupPolicy), m_adminSetting(adminSetting) {}
- Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Argument::Visibility visibility, Settings::TogglePolicy::Policy groupPolicy, Settings::AdminSetting adminSetting) :
+ Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Argument::Visibility visibility, Settings::TogglePolicy::Policy groupPolicy, Settings::BoolAdminSetting adminSetting) :
m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_type(type), m_visibility(visibility), m_groupPolicy(groupPolicy), m_adminSetting(adminSetting) {}
+ Argument(Execution::Args::Type execArgType, Resource::StringId desc, ArgumentType type, Settings::ExperimentalFeature::Feature feature, Settings::TogglePolicy::Policy groupPolicy, Settings::BoolAdminSetting adminSetting) :
+ m_argCommon(ArgumentCommon::ForType(execArgType)), m_desc(std::move(desc)), m_type(type), m_feature(feature), m_groupPolicy(groupPolicy), m_adminSetting(adminSetting) {}
+
ArgumentCommon m_argCommon;
Resource::StringId m_desc;
bool m_required = false;
@@ -251,6 +255,6 @@ namespace AppInstaller::CLI
size_t m_countLimit = 1;
Settings::ExperimentalFeature::Feature m_feature = Settings::ExperimentalFeature::Feature::None;
Settings::TogglePolicy::Policy m_groupPolicy = Settings::TogglePolicy::Policy::None;
- Settings::AdminSetting m_adminSetting = Settings::AdminSetting::Unknown;
+ Settings::BoolAdminSetting m_adminSetting = Settings::BoolAdminSetting::Unknown;
};
}
diff --git a/src/AppInstallerCLICore/Command.cpp b/src/AppInstallerCLICore/Command.cpp
index dec1945adf..408b7adfe7 100644
--- a/src/AppInstallerCLICore/Command.cpp
+++ b/src/AppInstallerCLICore/Command.cpp
@@ -637,7 +637,7 @@ namespace AppInstaller::CLI
throw GroupPolicyException(arg.GroupPolicy());
}
- if (arg.AdminSetting() != AdminSetting::Unknown && !Settings::IsAdminSettingEnabled(arg.AdminSetting()) && execArgs.Contains(arg.ExecArgType()))
+ if (arg.AdminSetting() != BoolAdminSetting::Unknown && !Settings::IsAdminSettingEnabled(arg.AdminSetting()) && execArgs.Contains(arg.ExecArgType()))
{
auto setting = Settings::AdminSettingToString(arg.AdminSetting());
AICLI_LOG(CLI, Error, << "Trying to use argument: " << arg.Name() << " disabled by admin setting " << setting);
diff --git a/src/AppInstallerCLICore/Commands/DownloadCommand.cpp b/src/AppInstallerCLICore/Commands/DownloadCommand.cpp
index 39739feeaf..b2b7d3ec15 100644
--- a/src/AppInstallerCLICore/Commands/DownloadCommand.cpp
+++ b/src/AppInstallerCLICore/Commands/DownloadCommand.cpp
@@ -36,8 +36,8 @@ namespace AppInstaller::CLI
Argument::ForType(Args::Type::CustomHeader),
Argument::ForType(Args::Type::AuthenticationMode),
Argument::ForType(Args::Type::AuthenticationAccount),
- Argument::ForType(Execution::Args::Type::AcceptPackageAgreements),
- Argument::ForType(Execution::Args::Type::AcceptSourceAgreements),
+ Argument::ForType(Args::Type::AcceptPackageAgreements),
+ Argument::ForType(Args::Type::AcceptSourceAgreements),
};
}
diff --git a/src/AppInstallerCLICore/Commands/RootCommand.cpp b/src/AppInstallerCLICore/Commands/RootCommand.cpp
index fc0c6b7cb3..f5a61d79fa 100644
--- a/src/AppInstallerCLICore/Commands/RootCommand.cpp
+++ b/src/AppInstallerCLICore/Commands/RootCommand.cpp
@@ -124,13 +124,21 @@ namespace AppInstaller::CLI
Execution::TableOutput<2> adminSettingsTable{ context.Reporter, { Resource::String::AdminSettingHeader, Resource::String::StateHeader } };
// Output the admin settings.
- for (const auto& setting : Settings::GetAllAdminSettings())
+ for (const auto& setting : Settings::GetAllBoolAdminSettings())
{
adminSettingsTable.OutputLine({
std::string{ AdminSettingToString(setting)},
Resource::LocString{ IsAdminSettingEnabled(setting) ? Resource::String::StateEnabled : Resource::String::StateDisabled }
});
}
+ for (const auto& setting : Settings::GetAllStringAdminSettings())
+ {
+ auto settingValue = GetAdminSetting(setting);
+ adminSettingsTable.OutputLine({
+ std::string{ AdminSettingToString(setting)},
+ settingValue ? Utility::LocIndString{ settingValue.value() } : Resource::LocString{ Resource::String::StateDisabled }
+ });
+ }
adminSettingsTable.Complete();
}
diff --git a/src/AppInstallerCLICore/Commands/SettingsCommand.cpp b/src/AppInstallerCLICore/Commands/SettingsCommand.cpp
index 55c436e631..70620f5bca 100644
--- a/src/AppInstallerCLICore/Commands/SettingsCommand.cpp
+++ b/src/AppInstallerCLICore/Commands/SettingsCommand.cpp
@@ -20,6 +20,8 @@ namespace AppInstaller::CLI
{
return InitializeFromMoveOnly>>({
std::make_unique(FullName()),
+ std::make_unique(FullName()),
+ std::make_unique(FullName()),
});
}
@@ -49,21 +51,20 @@ namespace AppInstaller::CLI
void SettingsCommand::ValidateArgumentsInternal(Execution::Args& execArgs) const
{
// Get admin setting string for all available options except Unknown
- using AdminSetting_t = std::underlying_type_t;
std::vector adminSettingList;
- for (AdminSetting_t i = 1 + static_cast(AdminSetting::Unknown); i < static_cast(AdminSetting::Max); ++i)
+ for (auto setting : GetAllSequentialEnumValues(BoolAdminSetting::Unknown))
{
- adminSettingList.emplace_back(AdminSettingToString(static_cast(i)));
+ adminSettingList.emplace_back(AdminSettingToString(setting));
}
Utility::LocIndString validOptions = Join(", "_liv, adminSettingList);
- if (execArgs.Contains(Execution::Args::Type::AdminSettingEnable) && AdminSetting::Unknown == StringToAdminSetting(execArgs.GetArg(Execution::Args::Type::AdminSettingEnable)))
+ if (execArgs.Contains(Execution::Args::Type::AdminSettingEnable) && BoolAdminSetting::Unknown == StringToBoolAdminSetting(execArgs.GetArg(Execution::Args::Type::AdminSettingEnable)))
{
throw CommandException(Resource::String::InvalidArgumentValueError(ArgumentCommon::ForType(Execution::Args::Type::AdminSettingEnable).Name, validOptions));
}
- if (execArgs.Contains(Execution::Args::Type::AdminSettingDisable) && AdminSetting::Unknown == StringToAdminSetting(execArgs.GetArg(Execution::Args::Type::AdminSettingDisable)))
+ if (execArgs.Contains(Execution::Args::Type::AdminSettingDisable) && BoolAdminSetting::Unknown == StringToBoolAdminSetting(execArgs.GetArg(Execution::Args::Type::AdminSettingDisable)))
{
throw CommandException(Resource::String::InvalidArgumentValueError(ArgumentCommon::ForType(Execution::Args::Type::AdminSettingDisable).Name, validOptions));
}
@@ -110,4 +111,103 @@ namespace AppInstaller::CLI
context <<
Workflow::ExportSettings;
}
+
+ std::vector SettingsSetCommand::GetArguments() const
+ {
+ return {
+ Argument { Execution::Args::Type::SettingName, Resource::String::SettingNameArgumentDescription, ArgumentType::Positional, true },
+ Argument { Execution::Args::Type::SettingValue, Resource::String::SettingValueArgumentDescription, ArgumentType::Positional, true },
+ };
+ }
+
+ Resource::LocString SettingsSetCommand::ShortDescription() const
+ {
+ return { Resource::String::SettingsSetCommandShortDescription };
+ }
+
+ Resource::LocString SettingsSetCommand::LongDescription() const
+ {
+ return { Resource::String::SettingsSetCommandLongDescription };
+ }
+
+ Utility::LocIndView SettingsSetCommand::HelpLink() const
+ {
+ return s_SettingsCommand_HelpLink;
+ }
+
+ void SettingsSetCommand::ValidateArgumentsInternal(Execution::Args& execArgs) const
+ {
+ // Get admin setting string for all available options except Unknown
+ std::vector adminSettingList;
+ for (auto setting : GetAllSequentialEnumValues(StringAdminSetting::Unknown))
+ {
+ adminSettingList.emplace_back(AdminSettingToString(setting));
+ }
+
+ Utility::LocIndString validOptions = Join(", "_liv, adminSettingList);
+
+ if (StringAdminSetting::Unknown == StringToStringAdminSetting(execArgs.GetArg(Execution::Args::Type::SettingName)))
+ {
+ throw CommandException(Resource::String::InvalidArgumentValueError(ArgumentCommon::ForType(Execution::Args::Type::SettingName).Name, validOptions));
+ }
+ }
+
+ void SettingsSetCommand::ExecuteInternal(Execution::Context& context) const
+ {
+ context <<
+ Workflow::EnsureRunningAsAdmin <<
+ Workflow::SetAdminSetting;
+ }
+
+ std::vector SettingsResetCommand::GetArguments() const
+ {
+ return {
+ Argument { Execution::Args::Type::SettingName, Resource::String::SettingNameArgumentDescription, ArgumentType::Positional, true },
+ };
+ }
+
+ Resource::LocString SettingsResetCommand::ShortDescription() const
+ {
+ return { Resource::String::SettingsResetCommandShortDescription };
+ }
+
+ Resource::LocString SettingsResetCommand::LongDescription() const
+ {
+ return { Resource::String::SettingsResetCommandLongDescription };
+ }
+
+ Utility::LocIndView SettingsResetCommand::HelpLink() const
+ {
+ return s_SettingsCommand_HelpLink;
+ }
+
+ void SettingsResetCommand::ValidateArgumentsInternal(Execution::Args& execArgs) const
+ {
+ // Get admin setting string for all available options except Unknown.
+ // We accept both bool and string settings
+ std::vector adminSettingList;
+ for (auto setting : GetAllSequentialEnumValues(BoolAdminSetting::Unknown))
+ {
+ adminSettingList.emplace_back(AdminSettingToString(setting));
+ }
+ for (auto setting : GetAllSequentialEnumValues(StringAdminSetting::Unknown))
+ {
+ adminSettingList.emplace_back(AdminSettingToString(setting));
+ }
+
+ Utility::LocIndString validOptions = Join(", "_liv, adminSettingList);
+
+ if (StringAdminSetting::Unknown == StringToStringAdminSetting(execArgs.GetArg(Execution::Args::Type::SettingName))
+ && BoolAdminSetting::Unknown == StringToBoolAdminSetting(execArgs.GetArg(Execution::Args::Type::SettingName)))
+ {
+ throw CommandException(Resource::String::InvalidArgumentValueError(ArgumentCommon::ForType(Execution::Args::Type::SettingName).Name, validOptions));
+ }
+ }
+
+ void SettingsResetCommand::ExecuteInternal(Execution::Context& context) const
+ {
+ context <<
+ Workflow::EnsureRunningAsAdmin <<
+ Workflow::ResetAdminSetting;
+ }
}
diff --git a/src/AppInstallerCLICore/Commands/SettingsCommand.h b/src/AppInstallerCLICore/Commands/SettingsCommand.h
index aee6cffbfd..78cb164da2 100644
--- a/src/AppInstallerCLICore/Commands/SettingsCommand.h
+++ b/src/AppInstallerCLICore/Commands/SettingsCommand.h
@@ -34,4 +34,36 @@ namespace AppInstaller::CLI
protected:
void ExecuteInternal(Execution::Context& context) const override;
};
+
+ struct SettingsSetCommand final : public Command
+ {
+ SettingsSetCommand(std::string_view parent) : Command("set", {}, parent, Settings::TogglePolicy::Policy::Settings) {}
+
+ std::vector GetArguments() const override;
+
+ virtual Resource::LocString ShortDescription() const override;
+ virtual Resource::LocString LongDescription() const override;
+
+ Utility::LocIndView HelpLink() const override;
+
+ protected:
+ void ValidateArgumentsInternal(Execution::Args& execArgs) const override;
+ void ExecuteInternal(Execution::Context& context) const override;
+ };
+
+ struct SettingsResetCommand final : public Command
+ {
+ SettingsResetCommand(std::string_view parent) : Command("reset", {}, parent, Settings::TogglePolicy::Policy::Settings) {}
+
+ std::vector GetArguments() const override;
+
+ virtual Resource::LocString ShortDescription() const override;
+ virtual Resource::LocString LongDescription() const override;
+
+ Utility::LocIndView HelpLink() const override;
+
+ protected:
+ void ValidateArgumentsInternal(Execution::Args& execArgs) const override;
+ void ExecuteInternal(Execution::Context& context) const override;
+ };
}
diff --git a/src/AppInstallerCLICore/Core.cpp b/src/AppInstallerCLICore/Core.cpp
index 89d5c892eb..fe19bb0aec 100644
--- a/src/AppInstallerCLICore/Core.cpp
+++ b/src/AppInstallerCLICore/Core.cpp
@@ -119,13 +119,6 @@ namespace AppInstaller::CLI
Logging::Telemetry().LogCommand(command->FullName());
command->ParseArguments(invocation, context.Args);
-
- // Change logging level to Info if Verbose not requested
- if (context.Args.Contains(Execution::Args::Type::VerboseLogs))
- {
- Logging::Log().SetLevel(Logging::Level::Verbose);
- }
-
context.UpdateForArgs();
context.SetExecutingCommand(command.get());
command->ValidateArguments(context.Args);
diff --git a/src/AppInstallerCLICore/ExecutionArgs.h b/src/AppInstallerCLICore/ExecutionArgs.h
index ad1b70496a..8ea1e0754d 100644
--- a/src/AppInstallerCLICore/ExecutionArgs.h
+++ b/src/AppInstallerCLICore/ExecutionArgs.h
@@ -89,6 +89,8 @@ namespace AppInstaller::CLI::Execution
// Setting Command
AdminSettingEnable,
AdminSettingDisable,
+ SettingName,
+ SettingValue,
// Upgrade command
All, // Used in Update command to update all installed packages to latest
@@ -140,6 +142,10 @@ namespace AppInstaller::CLI::Execution
AuthenticationMode, // Authentication mode (silent, silentPreferred or interactive)
AuthenticationAccount, // Authentication account to be used
+ // Network Behavior
+ Proxy, // Set a proxy to use in this execution
+ NoProxy, // Do not use the default proxy
+
ToolVersion,
// Used for demonstration purposes
diff --git a/src/AppInstallerCLICore/ExecutionContext.cpp b/src/AppInstallerCLICore/ExecutionContext.cpp
index 48fd668ee6..d8ecb88b1c 100644
--- a/src/AppInstallerCLICore/ExecutionContext.cpp
+++ b/src/AppInstallerCLICore/ExecutionContext.cpp
@@ -9,6 +9,7 @@
#include
#include
#include
+#include
using namespace AppInstaller::Checkpoints;
@@ -349,6 +350,23 @@ namespace AppInstaller::CLI::Execution
void Context::UpdateForArgs()
{
+ // Change logging level to Info if Verbose not requested
+ if (Args.Contains(Args::Type::VerboseLogs))
+ {
+ Logging::Log().SetLevel(Logging::Level::Verbose);
+ }
+
+ // Set proxy
+ if (Args.Contains(Args::Type::Proxy))
+ {
+ Network().SetProxyUri(std::string{ Args.GetArg(Args::Type::Proxy) });
+ }
+ else if (Args.Contains(Args::Type::NoProxy))
+ {
+ Network().SetProxyUri(std::nullopt);
+ }
+
+ // Set visual style
if (Args.Contains(Args::Type::NoVT))
{
Reporter.SetStyle(VisualStyle::NoVT);
diff --git a/src/AppInstallerCLICore/ExecutionContextData.h b/src/AppInstallerCLICore/ExecutionContextData.h
index e19b8d7233..b1f5e42110 100644
--- a/src/AppInstallerCLICore/ExecutionContextData.h
+++ b/src/AppInstallerCLICore/ExecutionContextData.h
@@ -276,6 +276,7 @@ namespace AppInstaller::CLI::Execution
using value_t = std::string;
};
+
template<>
struct DataMapping
{
diff --git a/src/AppInstallerCLICore/Resources.h b/src/AppInstallerCLICore/Resources.h
index 65bb45e870..a05c3c691a 100644
--- a/src/AppInstallerCLICore/Resources.h
+++ b/src/AppInstallerCLICore/Resources.h
@@ -339,15 +339,16 @@ namespace AppInstaller::CLI::Resource
WINGET_DEFINE_RESOURCE_STRINGID(NestedInstallerNotFound);
WINGET_DEFINE_RESOURCE_STRINGID(NestedInstallerNotSpecified);
WINGET_DEFINE_RESOURCE_STRINGID(NestedInstallerNotSupported);
- WINGET_DEFINE_RESOURCE_STRINGID(NoApplicableInstallers);
WINGET_DEFINE_RESOURCE_STRINGID(NoAdminRepairForUserScopePackage);
+ WINGET_DEFINE_RESOURCE_STRINGID(NoApplicableInstallers);
WINGET_DEFINE_RESOURCE_STRINGID(NoExperimentalFeaturesMessage);
WINGET_DEFINE_RESOURCE_STRINGID(NoInstalledPackageFound);
WINGET_DEFINE_RESOURCE_STRINGID(NoPackageFound);
WINGET_DEFINE_RESOURCE_STRINGID(NoPackageSelectionArgumentProvided);
WINGET_DEFINE_RESOURCE_STRINGID(NoPackagesFoundInImportFile);
- WINGET_DEFINE_RESOURCE_STRINGID(Notes);
+ WINGET_DEFINE_RESOURCE_STRINGID(NoProxyArgumentDescription);
WINGET_DEFINE_RESOURCE_STRINGID(NoRepairInfoFound);
+ WINGET_DEFINE_RESOURCE_STRINGID(Notes);
WINGET_DEFINE_RESOURCE_STRINGID(NoUninstallInfoFound);
WINGET_DEFINE_RESOURCE_STRINGID(NoUpgradeArgumentDescription);
WINGET_DEFINE_RESOURCE_STRINGID(NoVTArgumentDescription);
@@ -414,6 +415,7 @@ namespace AppInstaller::CLI::Resource
WINGET_DEFINE_RESOURCE_STRINGID(PromptOptionNo);
WINGET_DEFINE_RESOURCE_STRINGID(PromptOptionYes);
WINGET_DEFINE_RESOURCE_STRINGID(PromptToProceed);
+ WINGET_DEFINE_RESOURCE_STRINGID(ProxyArgumentDescription);
WINGET_DEFINE_RESOURCE_STRINGID(PurgeArgumentDescription);
WINGET_DEFINE_RESOURCE_STRINGID(PurgeInstallDirectory);
WINGET_DEFINE_RESOURCE_STRINGID(QueryArgumentDescription);
@@ -437,6 +439,8 @@ namespace AppInstaller::CLI::Resource
WINGET_DEFINE_RESOURCE_STRINGID(ReportIdentityFound);
WINGET_DEFINE_RESOURCE_STRINGID(RequiredArgError);
WINGET_DEFINE_RESOURCE_STRINGID(ReservedFilenameError);
+ WINGET_DEFINE_RESOURCE_STRINGID(ResetAdminSettingFailed);
+ WINGET_DEFINE_RESOURCE_STRINGID(ResetAdminSettingSucceeded);
WINGET_DEFINE_RESOURCE_STRINGID(ResumeCommandLongDescription);
WINGET_DEFINE_RESOURCE_STRINGID(ResumeCommandShortDescription);
WINGET_DEFINE_RESOURCE_STRINGID(ResumeIdArgumentDescription);
@@ -457,14 +461,22 @@ namespace AppInstaller::CLI::Resource
WINGET_DEFINE_RESOURCE_STRINGID(SearchTruncated);
WINGET_DEFINE_RESOURCE_STRINGID(SearchVersion);
WINGET_DEFINE_RESOURCE_STRINGID(SeeLineAndColumn);
+ WINGET_DEFINE_RESOURCE_STRINGID(SetAdminSettingFailed);
+ WINGET_DEFINE_RESOURCE_STRINGID(SetAdminSettingSucceeded);
WINGET_DEFINE_RESOURCE_STRINGID(SettingLoadFailure);
+ WINGET_DEFINE_RESOURCE_STRINGID(SettingNameArgumentDescription);
WINGET_DEFINE_RESOURCE_STRINGID(SettingsCommandLongDescription);
WINGET_DEFINE_RESOURCE_STRINGID(SettingsCommandShortDescription);
WINGET_DEFINE_RESOURCE_STRINGID(SettingsExportCommandLongDescription);
WINGET_DEFINE_RESOURCE_STRINGID(SettingsExportCommandShortDescription);
+ WINGET_DEFINE_RESOURCE_STRINGID(SettingsResetCommandLongDescription);
+ WINGET_DEFINE_RESOURCE_STRINGID(SettingsResetCommandShortDescription);
+ WINGET_DEFINE_RESOURCE_STRINGID(SettingsSetCommandLongDescription);
+ WINGET_DEFINE_RESOURCE_STRINGID(SettingsSetCommandShortDescription);
WINGET_DEFINE_RESOURCE_STRINGID(SettingsWarningField);
WINGET_DEFINE_RESOURCE_STRINGID(SettingsWarnings);
WINGET_DEFINE_RESOURCE_STRINGID(SettingsWarningValue);
+ WINGET_DEFINE_RESOURCE_STRINGID(SettingValueArgumentDescription);
WINGET_DEFINE_RESOURCE_STRINGID(ShowChannel);
WINGET_DEFINE_RESOURCE_STRINGID(ShowCommandLongDescription);
WINGET_DEFINE_RESOURCE_STRINGID(ShowCommandShortDescription);
@@ -589,8 +601,8 @@ namespace AppInstaller::CLI::Resource
WINGET_DEFINE_RESOURCE_STRINGID(UpdateNotApplicableReason);
WINGET_DEFINE_RESOURCE_STRINGID(UpgradeArgumentDescription);
WINGET_DEFINE_RESOURCE_STRINGID(UpgradeAvailableForPinned);
- WINGET_DEFINE_RESOURCE_STRINGID(UpgradeBlockedByPinCount);
WINGET_DEFINE_RESOURCE_STRINGID(UpgradeBlockedByManifest);
+ WINGET_DEFINE_RESOURCE_STRINGID(UpgradeBlockedByPinCount);
WINGET_DEFINE_RESOURCE_STRINGID(UpgradeCommandLongDescription);
WINGET_DEFINE_RESOURCE_STRINGID(UpgradeCommandShortDescription);
WINGET_DEFINE_RESOURCE_STRINGID(UpgradeDifferentInstallTechnology);
diff --git a/src/AppInstallerCLICore/Workflows/ArchiveFlow.cpp b/src/AppInstallerCLICore/Workflows/ArchiveFlow.cpp
index c273fd827a..069598e45b 100644
--- a/src/AppInstallerCLICore/Workflows/ArchiveFlow.cpp
+++ b/src/AppInstallerCLICore/Workflows/ArchiveFlow.cpp
@@ -29,7 +29,7 @@ namespace AppInstaller::CLI::Workflow
else
{
if (context.Args.Contains(Execution::Args::Type::IgnoreLocalArchiveMalwareScan) &&
- Settings::IsAdminSettingEnabled(Settings::AdminSetting::LocalArchiveMalwareScanOverride))
+ Settings::IsAdminSettingEnabled(Settings::BoolAdminSetting::LocalArchiveMalwareScanOverride))
{
AICLI_LOG(CLI, Warning, << "Archive scan detected malware. Proceeding due to --ignore-local-archive-malware-scan");
context.Reporter.Warn() << Resource::String::ArchiveFailedMalwareScanOverridden << std::endl;
diff --git a/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp b/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp
index 1bd4cd462a..618db03789 100644
--- a/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp
+++ b/src/AppInstallerCLICore/Workflows/DownloadFlow.cpp
@@ -7,13 +7,16 @@
#include
#include
#include
+#include
#include
+#include
namespace AppInstaller::CLI::Workflow
{
using namespace AppInstaller::Manifest;
using namespace AppInstaller::Repository;
using namespace AppInstaller::Utility;
+ using namespace AppInstaller::Settings;
using namespace std::string_view_literals;
namespace
@@ -211,14 +214,18 @@ namespace AppInstaller::CLI::Workflow
context << DownloadInstallerFile;
break;
case InstallerTypeEnum::Msix:
- if (installer.SignatureSha256.empty() || installerDownloadOnly)
+ // If the signature hash is provided in the manifest and we are doing an install,
+ // we can just verify signature hash without a full download and do a streaming install.
+ // Even if we have the signature hash, we still do a full download if InstallerDownloadOnly
+ // flag is set, or if we need to use a proxy (as deployment APIs won't use proxy for us).
+ if (installer.SignatureSha256.empty()
+ || installerDownloadOnly
+ || Network().GetProxyUri())
{
- // If InstallerDownloadOnly flag is set, always download the installer file.
context << DownloadInstallerFile;
}
else
{
- // Signature hash provided. No download needed. Just verify signature hash.
context << GetMsixSignatureHash;
}
break;
@@ -386,6 +393,7 @@ namespace AppInstaller::CLI::Workflow
{
const auto& installer = context.Get().value();
+ // Signature hash is only used for streaming installs, which don't use proxy
Msix::MsixInfo msixInfo(installer.Url);
auto signatureHash = msixInfo.GetSignatureHash();
@@ -422,7 +430,7 @@ namespace AppInstaller::CLI::Workflow
{
context.Reporter.Error() << Resource::String::InstallerHashMismatchAdminBlock << std::endl;
}
- else if (!Settings::IsAdminSettingEnabled(Settings::AdminSetting::InstallerHashOverride))
+ else if (!Settings::IsAdminSettingEnabled(Settings::BoolAdminSetting::InstallerHashOverride))
{
context.Reporter.Error() << Resource::String::InstallerHashMismatchError << std::endl;
}
diff --git a/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp b/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp
index da2d5c8198..49eca405cd 100644
--- a/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp
+++ b/src/AppInstallerCLICore/Workflows/SettingsFlow.cpp
@@ -23,12 +23,22 @@ namespace AppInstaller::CLI::Workflow
root["userSettingsFile"] = UserSettings::SettingsFilePath().u8string();
}
- void AddAdminSetting(AdminSetting setting)
+ void AddAdminSetting(BoolAdminSetting setting)
{
auto str = std::string{ Settings::AdminSettingToString(setting) };
root["adminSettings"][str] = Settings::IsAdminSettingEnabled(setting);
}
+ void AddAdminSetting(StringAdminSetting setting)
+ {
+ auto name = std::string{ Settings::AdminSettingToString(setting) };
+ auto value = Settings::GetAdminSetting(setting);
+ if (value)
+ {
+ root["adminSettings"][name] = value.value();
+ }
+ }
+
std::string ToJsonString() const
{
Json::StreamWriterBuilder writerBuilder;
@@ -44,7 +54,7 @@ namespace AppInstaller::CLI::Workflow
void EnableAdminSetting(Execution::Context& context)
{
auto adminSettingString = context.Args.GetArg(Execution::Args::Type::AdminSettingEnable);
- AdminSetting adminSetting = Settings::StringToAdminSetting(adminSettingString);
+ BoolAdminSetting adminSetting = Settings::StringToBoolAdminSetting(adminSettingString);
if (Settings::EnableAdminSetting(adminSetting))
{
context.Reporter.Info() << Resource::String::AdminSettingEnabled(AdminSettingToString(adminSetting)) << std::endl;
@@ -58,7 +68,7 @@ namespace AppInstaller::CLI::Workflow
void DisableAdminSetting(Execution::Context& context)
{
auto adminSettingString = context.Args.GetArg(Execution::Args::Type::AdminSettingDisable);
- AdminSetting adminSetting = Settings::StringToAdminSetting(adminSettingString);
+ BoolAdminSetting adminSetting = Settings::StringToBoolAdminSetting(adminSettingString);
if (Settings::DisableAdminSetting(adminSetting))
{
context.Reporter.Info() << Resource::String::AdminSettingDisabled(AdminSettingToString(adminSetting)) << std::endl;
@@ -69,6 +79,40 @@ namespace AppInstaller::CLI::Workflow
}
}
+ void SetAdminSetting(Execution::Context& context)
+ {
+ auto adminSettingName = context.Args.GetArg(Execution::Args::Type::SettingName);
+ auto adminSettingValue = context.Args.GetArg(Execution::Args::Type::SettingValue);
+ StringAdminSetting adminSetting = Settings::StringToStringAdminSetting(adminSettingName);
+ if (Settings::SetAdminSetting(adminSetting, adminSettingValue))
+ {
+ context.Reporter.Info() << Resource::String::SetAdminSettingSucceeded(LocIndString{ adminSettingName }, LocIndString{ adminSettingValue }) << std::endl;
+ }
+ else
+ {
+ context.Reporter.Error() << Resource::String::SetAdminSettingFailed(LocIndString{ adminSettingName }) << std::endl;
+ }
+ }
+
+ void ResetAdminSetting(Execution::Context& context)
+ {
+ auto adminSettingName = context.Args.GetArg(Execution::Args::Type::SettingName);
+
+ // Try as both bool and string setting as we don't know the type
+ auto boolAdminSetting = Settings::StringToBoolAdminSetting(adminSettingName);
+ auto stringAdminSetting = Settings::StringToStringAdminSetting(adminSettingName);
+
+ if ((boolAdminSetting != Settings::BoolAdminSetting::Unknown && Settings::DisableAdminSetting(boolAdminSetting))
+ || (stringAdminSetting != Settings::StringAdminSetting::Unknown && Settings::ResetAdminSetting(stringAdminSetting)))
+ {
+ context.Reporter.Info() << Resource::String::ResetAdminSettingSucceeded(LocIndString{ adminSettingName }) << std::endl;
+ }
+ else
+ {
+ context.Reporter.Error() << Resource::String::ResetAdminSettingFailed(LocIndString{ adminSettingName }) << std::endl;
+ }
+ }
+
void OpenUserSetting(Execution::Context& context)
{
// Show warnings only when the setting command is executed.
@@ -129,7 +173,12 @@ namespace AppInstaller::CLI::Workflow
{
ExportSettingsJson exportSettingsJson;
- for (const auto& setting : GetAllAdminSettings())
+ for (const auto& setting : GetAllBoolAdminSettings())
+ {
+ exportSettingsJson.AddAdminSetting(setting);
+ }
+
+ for (const auto& setting : GetAllStringAdminSettings())
{
exportSettingsJson.AddAdminSetting(setting);
}
diff --git a/src/AppInstallerCLICore/Workflows/SettingsFlow.h b/src/AppInstallerCLICore/Workflows/SettingsFlow.h
index e40a0051c9..50998295a5 100644
--- a/src/AppInstallerCLICore/Workflows/SettingsFlow.h
+++ b/src/AppInstallerCLICore/Workflows/SettingsFlow.h
@@ -17,6 +17,18 @@ namespace AppInstaller::CLI::Workflow
// Outputs: None
void DisableAdminSetting(Execution::Context& context);
+ // Sets the value of an admin setting.
+ // Required Args: SettingName, SettingValue
+ // Inputs: None
+ // Outputs: None
+ void SetAdminSetting(Execution::Context& context);
+
+ // Resets an admin setting to the default.
+ // Required Args: SettingName
+ // Inputs: None
+ // Outputs: None
+ void ResetAdminSetting(Execution::Context& context);
+
// Opens the user settings.
// Required Args: None
// Inputs: None
diff --git a/src/AppInstallerCLIE2ETests/GroupPolicyHelper.cs b/src/AppInstallerCLIE2ETests/GroupPolicyHelper.cs
index 2eb2fe0db6..8179934fa6 100644
--- a/src/AppInstallerCLIE2ETests/GroupPolicyHelper.cs
+++ b/src/AppInstallerCLIE2ETests/GroupPolicyHelper.cs
@@ -118,6 +118,11 @@ private GroupPolicyHelper(string name, string elementId)
///
public static GroupPolicyHelper EnableConfiguration { get; private set; } = new GroupPolicyHelper("EnableWindowsPackageManagerConfiguration");
+ ///
+ /// Gets the Enable Windows Package Manager proxy command line options policy.
+ ///
+ public static GroupPolicyHelper EnableProxyCommandLineOptions { get; private set; } = new GroupPolicyHelper("EnableWindowsPackageManagerProxyCommandLineOptions");
+
///
/// Gets the Enable auto update interval policy.
///
@@ -138,6 +143,7 @@ private GroupPolicyHelper(string name, string elementId)
SourceAutoUpdateInterval,
EnableWinGetCommandLineInterfaces,
EnableConfiguration,
+ EnableProxyCommandLineOptions,
};
///
diff --git a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw
index eba36a6e48..7f5838c20e 100644
--- a/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw
+++ b/src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw
@@ -2817,4 +2817,48 @@ Please specify one of them using the --source option to proceed.
The SQLite connection was terminated to prevent corruption.
+
+ Enable Windows Package Manager proxy command line options
+ Describes a Group Policy that can enable the use of the --proxy option to set a proxy
+
+
+ Set a proxy to use for this execution
+
+
+ Disable the use of proxy for this execution
+
+
+ Cannot reset {0}. This setting is controlled by policy. For more information contact your system administrator.
+ {Locked="{0}"} The value will be replaced with the feature name
+
+
+ Reset admin setting '{0}'.
+ {Locked="{0}"} Message displayed after the user resets an admin setting to its default value. Reset is used as verb in past tense. {0} is a placeholder replaced by the setting name.
+
+
+ Cannot set {0}. This setting is controlled by policy. For more information contact your system administrator.
+ {Locked="{0}"} The value will be replaced with the feature name
+
+
+ Set admin setting '{0}' to '{1}'.
+ {Locked="{0}"} Message displayed after the user sets the value of an admin setting. Set is used as a verb in past tense. {0} is a placeholder replaced by the setting name. {1} is a placeholder replaced
+
+
+ Name of the setting to modify
+
+
+ Value to set for the setting.
+
+
+ Resets an admin setting to its default value.
+
+
+ Resets an admin setting to its default value.
+
+
+ Sets the value of an admin setting.
+
+
+ Sets the value of an admin setting.
+
\ No newline at end of file
diff --git a/src/AppInstallerCLITests/AdminSettings.cpp b/src/AppInstallerCLITests/AdminSettings.cpp
index be05f13e71..a7fa9d2a15 100644
--- a/src/AppInstallerCLITests/AdminSettings.cpp
+++ b/src/AppInstallerCLITests/AdminSettings.cpp
@@ -16,21 +16,21 @@ TEST_CASE("AdminSetting_Enable", "[adminSettings]")
{
GroupPolicyTestOverride policies;
policies.SetState(TogglePolicy::Policy::LocalManifestFiles, PolicyState::NotConfigured);
- REQUIRE(EnableAdminSetting(AdminSetting::LocalManifestFiles));
+ REQUIRE(EnableAdminSetting(BoolAdminSetting::LocalManifestFiles));
}
SECTION("Enabled")
{
GroupPolicyTestOverride policies;
policies.SetState(TogglePolicy::Policy::LocalManifestFiles, PolicyState::Enabled);
- REQUIRE(EnableAdminSetting(AdminSetting::LocalManifestFiles));
+ REQUIRE(EnableAdminSetting(BoolAdminSetting::LocalManifestFiles));
}
SECTION("Disabled")
{
GroupPolicyTestOverride policies;
policies.SetState(TogglePolicy::Policy::LocalManifestFiles, PolicyState::Disabled);
- REQUIRE_FALSE(EnableAdminSetting(AdminSetting::LocalManifestFiles));
+ REQUIRE_FALSE(EnableAdminSetting(BoolAdminSetting::LocalManifestFiles));
}
}
}
@@ -43,21 +43,42 @@ TEST_CASE("AdminSetting_Disable", "[adminSettings]")
{
GroupPolicyTestOverride policies;
policies.SetState(TogglePolicy::Policy::LocalManifestFiles, PolicyState::NotConfigured);
- REQUIRE(DisableAdminSetting(AdminSetting::LocalManifestFiles));
+ REQUIRE(DisableAdminSetting(BoolAdminSetting::LocalManifestFiles));
}
SECTION("Enabled")
{
GroupPolicyTestOverride policies;
policies.SetState(TogglePolicy::Policy::LocalManifestFiles, PolicyState::Enabled);
- REQUIRE_FALSE(DisableAdminSetting(AdminSetting::LocalManifestFiles));
+ REQUIRE_FALSE(DisableAdminSetting(BoolAdminSetting::LocalManifestFiles));
}
SECTION("Disabled")
{
GroupPolicyTestOverride policies;
policies.SetState(TogglePolicy::Policy::LocalManifestFiles, PolicyState::Disabled);
- REQUIRE(DisableAdminSetting(AdminSetting::LocalManifestFiles));
+ REQUIRE(DisableAdminSetting(BoolAdminSetting::LocalManifestFiles));
}
}
}
+
+TEST_CASE("AdminSetting_AllSettingsAreImplemented", "[adminSettings]")
+{
+ for (auto adminSetting : GetAllBoolAdminSettings())
+ {
+ // If we forget to add it to the conversion, it returns Unknown/None
+ REQUIRE(AdminSettingToString(adminSetting) != AdminSettingToString(BoolAdminSetting::Unknown));
+ REQUIRE(StringToBoolAdminSetting(AdminSettingToString(adminSetting)) != BoolAdminSetting::Unknown);
+ REQUIRE(GetAdminSettingPolicy(adminSetting) != TogglePolicy::Policy::None);
+
+ GroupPolicyTestOverride policies;
+ policies.SetState(GetAdminSettingPolicy(adminSetting), PolicyState::NotConfigured);
+
+ // We should be able to configure the state.
+ // If we forget to add it, it won't persist.
+ REQUIRE(EnableAdminSetting(adminSetting));
+ REQUIRE(IsAdminSettingEnabled(adminSetting));
+ REQUIRE(DisableAdminSetting(adminSetting));
+ REQUIRE_FALSE(IsAdminSettingEnabled(adminSetting));
+ }
+}
\ No newline at end of file
diff --git a/src/AppInstallerCLITests/CustomHeader.cpp b/src/AppInstallerCLITests/CustomHeader.cpp
index a8f3a2bf7a..1501d4cd95 100644
--- a/src/AppInstallerCLITests/CustomHeader.cpp
+++ b/src/AppInstallerCLITests/CustomHeader.cpp
@@ -54,7 +54,7 @@ TEST_CASE("RestClient_CustomHeader", "[RestSource][CustomHeader]")
std::optional customHeader = "Testing custom header";
auto header = std::make_pair<>(CustomHeaderName, JSON::GetUtilityString(customHeader.value()));
HttpClientHelper helper{ GetHeaderVerificationHandler(web::http::status_codes::OK, sample, header) };
- RestClient client = RestClient::Create(utility::conversions::to_utf8string("https://restsource.com/api"), customHeader, {}, {}, std::move(helper));
+ RestClient client = RestClient::Create(utility::conversions::to_utf8string("https://restsource.com/api"), customHeader, {}, std::move(helper), {});
REQUIRE(client.GetSourceIdentifier() == "Source123");
}
@@ -66,7 +66,7 @@ TEST_CASE("RestSourceSearch_CustomHeader", "[RestSource][CustomHeader]")
std::unordered_map headers;
headers.emplace(CustomHeaderName, customHeader);
- V1_1::Interface v1_1{ "https://restsource.com/api", {}, headers, std::move(helper) };
+ V1_1::Interface v1_1{ "https://restsource.com/api", std::move(helper) , {}, headers};
Schema::IRestClient::SearchResult searchResponse = v1_1.Search({});
REQUIRE(searchResponse.Matches.size() == 1);
Schema::IRestClient::Package package = searchResponse.Matches.at(0);
@@ -80,7 +80,7 @@ TEST_CASE("RestSourceSearch_WhitespaceCustomHeader", "[RestSource][CustomHeader]
std::unordered_map headers;
headers.emplace(CustomHeaderName, customHeader);
- V1_1::Interface v1_1{ "https://restsource.com/api", {}, headers, std::move(helper) };
+ V1_1::Interface v1_1{ "https://restsource.com/api", std::move(helper), {}, headers };
Schema::IRestClient::SearchResult searchResponse = v1_1.Search({});
REQUIRE(searchResponse.Matches.size() == 1);
}
@@ -93,7 +93,7 @@ TEST_CASE("RestSourceSearch_NoCustomHeader", "[RestSource][CustomHeader]")
std::unordered_map headers;
headers.emplace(CustomHeaderName, customHeader);
- V1_1::Interface v1_1{ "https://restsource.com/api", {}, {}, std::move(helper) };
+ V1_1::Interface v1_1{ "https://restsource.com/api", std::move(helper), {}, {} };
REQUIRE_THROWS_HR(v1_1.Search({}), APPINSTALLER_CLI_ERROR_RESTSOURCE_INTERNAL_ERROR);
}
@@ -103,7 +103,7 @@ TEST_CASE("RestSourceSearch_CustomHeaderExceedingSize", "[RestSource][CustomHead
auto header = std::make_pair<>(CustomHeaderName, JSON::GetUtilityString(customHeader));
HttpClientHelper helper{ GetHeaderVerificationHandler(web::http::status_codes::OK, sampleSearchResponse, header) };
- REQUIRE_THROWS_HR(RestClient::Create(utility::conversions::to_utf8string("https://restsource.com/api"), customHeader, {}, {}, std::move(helper)),
+ REQUIRE_THROWS_HR(RestClient::Create(utility::conversions::to_utf8string("https://restsource.com/api"), customHeader, {}, std::move(helper), {}),
APPINSTALLER_CLI_ERROR_CUSTOMHEADER_EXCEEDS_MAXLENGTH);
}
@@ -121,7 +121,7 @@ TEST_CASE("RestClient_CustomUserAgentHeader", "[RestSource][CustomHeader]")
std::string testCaller = "TestCaller";
auto header = std::make_pair<>(web::http::header_names::user_agent, JSON::GetUtilityString(Runtime::GetUserAgent(testCaller)));
HttpClientHelper helper{ GetHeaderVerificationHandler(web::http::status_codes::OK, sample, header) };
- RestClient client = RestClient::Create(utility::conversions::to_utf8string("https://restsource.com/api"), {}, testCaller, {}, std::move(helper));
+ RestClient client = RestClient::Create(utility::conversions::to_utf8string("https://restsource.com/api"), {}, testCaller, std::move(helper), {});
REQUIRE(client.GetSourceIdentifier() == "Source123");
}
@@ -138,6 +138,6 @@ TEST_CASE("RestClient_DefaultUserAgentHeader", "[RestSource][CustomHeader]")
auto header = std::make_pair<>(web::http::header_names::user_agent, JSON::GetUtilityString(Runtime::GetDefaultUserAgent()));
HttpClientHelper helper{ GetHeaderVerificationHandler(web::http::status_codes::OK, sample, header) };
- RestClient client = RestClient::Create(utility::conversions::to_utf8string("https://restsource.com/api"), {}, {}, {}, std::move(helper));
+ RestClient client = RestClient::Create(utility::conversions::to_utf8string("https://restsource.com/api"), {}, {}, std::move(helper), {});
REQUIRE(client.GetSourceIdentifier() == "Source123");
}
\ No newline at end of file
diff --git a/src/AppInstallerCLITests/GroupPolicy.cpp b/src/AppInstallerCLITests/GroupPolicy.cpp
index f57442c28f..4c8c2356ac 100644
--- a/src/AppInstallerCLITests/GroupPolicy.cpp
+++ b/src/AppInstallerCLITests/GroupPolicy.cpp
@@ -376,6 +376,7 @@ TEST_CASE("GroupPolicy_AllEnabled", "[groupPolicy]")
SetRegistryValue(policiesKey.get(), BypassCertificatePinningForMicrosoftStoreValueName, 1);
SetRegistryValue(policiesKey.get(), EnableWindowsPackageManagerCommandLineInterfaces, 1);
SetRegistryValue(policiesKey.get(), ConfigurationPolicyValueName, 1);
+ SetRegistryValue(policiesKey.get(), ProxyCommandLineOptionsPolicyValueName, 1);
GroupPolicy groupPolicy{ policiesKey.get() };
for (const auto& policy : TogglePolicy::GetAllPolicies())
diff --git a/src/AppInstallerCLITests/InstallFlow.cpp b/src/AppInstallerCLITests/InstallFlow.cpp
index 56f117bceb..a52dd702a1 100644
--- a/src/AppInstallerCLITests/InstallFlow.cpp
+++ b/src/AppInstallerCLITests/InstallFlow.cpp
@@ -450,7 +450,7 @@ TEST_CASE("InstallFlow_Zip_ArchiveScanOverride_AdminSettingDisabled", "[InstallF
context.Args.AddArg(Execution::Args::Type::Manifest, TestDataFile("InstallFlowTest_Zip_Exe.yaml").GetPath().u8string());
context.Args.AddArg(Execution::Args::Type::IgnoreLocalArchiveMalwareScan);
- DisableAdminSetting(AppInstaller::Settings::AdminSetting::LocalArchiveMalwareScanOverride);
+ DisableAdminSetting(AppInstaller::Settings::BoolAdminSetting::LocalArchiveMalwareScanOverride);
TestHook::SetScanArchiveResult_Override scanArchiveResultOverride(false);
@@ -478,7 +478,7 @@ TEST_CASE("InstallFlow_Zip_ArchiveScanOverride_AdminSettingEnabled", "[InstallFl
context.Args.AddArg(Execution::Args::Type::Manifest, TestDataFile("InstallFlowTest_Zip_Exe.yaml").GetPath().u8string());
context.Args.AddArg(Execution::Args::Type::IgnoreLocalArchiveMalwareScan);
- EnableAdminSetting(AppInstaller::Settings::AdminSetting::LocalArchiveMalwareScanOverride);
+ EnableAdminSetting(AppInstaller::Settings::BoolAdminSetting::LocalArchiveMalwareScanOverride);
TestHook::SetScanArchiveResult_Override scanArchiveResultOverride(false);
diff --git a/src/AppInstallerCLITests/RestClient.cpp b/src/AppInstallerCLITests/RestClient.cpp
index 00af2e2a27..d7ad277a73 100644
--- a/src/AppInstallerCLITests/RestClient.cpp
+++ b/src/AppInstallerCLITests/RestClient.cpp
@@ -47,11 +47,11 @@ TEST_CASE("GetSupportedInterface", "[RestSource]")
IRestClient::Information info{ "TestId", { "1.0.0" } };
Version version{ "1.0.0" };
- REQUIRE(RestClient::GetSupportedInterface(TestRestUri, {}, info, {}, version)->GetVersion() == version);
+ REQUIRE(RestClient::GetSupportedInterface(TestRestUri, {}, info, {}, version, {})->GetVersion() == version);
// Update this test to next version so that we don't forget to add to supported versions before rest e2e tests are available.
Version invalid{ "1.8.0" };
- REQUIRE_THROWS_HR(RestClient::GetSupportedInterface(TestRestUri, {}, info, {}, invalid), APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_VERSION);
+ REQUIRE_THROWS_HR(RestClient::GetSupportedInterface(TestRestUri, {}, info, {}, invalid, {}), APPINSTALLER_CLI_ERROR_RESTSOURCE_INVALID_VERSION);
Authentication::AuthenticationArguments authArgs;
authArgs.Mode = Authentication::AuthenticationMode::Silent;
@@ -60,12 +60,12 @@ TEST_CASE("GetSupportedInterface", "[RestSource]")
// GetSupportedInterface throws on unknown authentication type.
IRestClient::Information infoWithUnknownAuthenticationType{ "TestId", { "1.7.0" } };
infoWithUnknownAuthenticationType.Authentication.Type = Authentication::AuthenticationType::Unknown;
- REQUIRE_THROWS_HR(RestClient::GetSupportedInterface(TestRestUri, {}, infoWithUnknownAuthenticationType, authArgs, version_1_7), APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED);
+ REQUIRE_THROWS_HR(RestClient::GetSupportedInterface(TestRestUri, {}, infoWithUnknownAuthenticationType, authArgs, version_1_7, {}), APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED);
// GetSupportedInterface throws on invalid authentication info.
IRestClient::Information infoWithInvalidAuthenticationInfo{ "TestId", { "1.7.0" } };
infoWithInvalidAuthenticationInfo.Authentication.Type = Authentication::AuthenticationType::MicrosoftEntraId;
- REQUIRE_THROWS_HR(RestClient::GetSupportedInterface(TestRestUri, {}, infoWithInvalidAuthenticationInfo, authArgs, version_1_7), APPINSTALLER_CLI_ERROR_INVALID_AUTHENTICATION_INFO);
+ REQUIRE_THROWS_HR(RestClient::GetSupportedInterface(TestRestUri, {}, infoWithInvalidAuthenticationInfo, authArgs, version_1_7, {}), APPINSTALLER_CLI_ERROR_INVALID_AUTHENTICATION_INFO);
}
TEST_CASE("GetInformation_Success", "[RestSource]")
@@ -277,7 +277,7 @@ TEST_CASE("RestClientCreate_UnsupportedVersion", "[RestSource]")
}})delimiter");
HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, sample) };
- REQUIRE_THROWS_HR(RestClient::Create("https://restsource.com/api", {}, {}, {}, std::move(helper)), APPINSTALLER_CLI_ERROR_UNSUPPORTED_RESTSOURCE);
+ REQUIRE_THROWS_HR(RestClient::Create("https://restsource.com/api", {}, {}, std::move(helper)), APPINSTALLER_CLI_ERROR_UNSUPPORTED_RESTSOURCE);
}
TEST_CASE("RestClientCreate_UnsupportedAuthenticationMethod", "[RestSource]")
@@ -297,7 +297,7 @@ TEST_CASE("RestClientCreate_UnsupportedAuthenticationMethod", "[RestSource]")
HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, sample) };
Authentication::AuthenticationArguments authArgs;
authArgs.Mode = Authentication::AuthenticationMode::Silent;
- REQUIRE_THROWS_HR(RestClient::Create("https://restsource.com/api", {}, {}, std::move(authArgs), std::move(helper)), APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED);
+ REQUIRE_THROWS_HR(RestClient::Create("https://restsource.com/api", {}, {}, std::move(helper), std::move(authArgs)), APPINSTALLER_CLI_ERROR_AUTHENTICATION_TYPE_NOT_SUPPORTED);
}
TEST_CASE("RestClientCreate_InvalidAuthenticationArguments", "[RestSource]")
@@ -320,7 +320,7 @@ TEST_CASE("RestClientCreate_InvalidAuthenticationArguments", "[RestSource]")
HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, sample) };
Authentication::AuthenticationArguments authArgs;
authArgs.Mode = Authentication::AuthenticationMode::Unknown;
- REQUIRE_THROWS_HR(RestClient::Create("https://restsource.com/api", {}, {}, std::move(authArgs), std::move(helper)), E_UNEXPECTED);
+ REQUIRE_THROWS_HR(RestClient::Create("https://restsource.com/api", {}, {}, std::move(helper), std::move(authArgs)), E_UNEXPECTED);
}
TEST_CASE("RestClientCreate_1.0_Success", "[RestSource]")
@@ -335,7 +335,7 @@ TEST_CASE("RestClientCreate_1.0_Success", "[RestSource]")
}})delimiter");
HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, sample) };
- RestClient client = RestClient::Create(TestRestUri, {}, {}, {}, std::move(helper));
+ RestClient client = RestClient::Create(TestRestUri, {}, {}, std::move(helper), {});
REQUIRE(client.GetSourceIdentifier() == "Source123");
}
@@ -372,7 +372,7 @@ TEST_CASE("RestClientCreate_1.1_Success", "[RestSource]")
}})delimiter");
HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, sample) };
- RestClient client = RestClient::Create(TestRestUri, {}, {}, {}, std::move(helper));
+ RestClient client = RestClient::Create(TestRestUri, {}, {}, std::move(helper));
REQUIRE(client.GetSourceIdentifier() == "Source123");
auto information = client.GetSourceInformation();
REQUIRE(information.SourceAgreementsIdentifier == "agreementV1");
@@ -438,7 +438,7 @@ TEST_CASE("RestClientCreate_1.7_Success", "[RestSource]")
Authentication::AuthenticationArguments authArgs;
authArgs.Mode = Authentication::AuthenticationMode::Silent;
HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, sample) };
- RestClient client = RestClient::Create(TestRestUri, {}, {}, std::move(authArgs), std::move(helper));
+ RestClient client = RestClient::Create(TestRestUri, {}, {}, std::move(helper), std::move(authArgs));
REQUIRE(client.GetSourceIdentifier() == "Source123");
auto information = client.GetSourceInformation();
REQUIRE(information.SourceAgreementsIdentifier == "agreementV1");
diff --git a/src/AppInstallerCLITests/RestInterface_1_1.cpp b/src/AppInstallerCLITests/RestInterface_1_1.cpp
index a167c03427..3334388146 100644
--- a/src/AppInstallerCLITests/RestInterface_1_1.cpp
+++ b/src/AppInstallerCLITests/RestInterface_1_1.cpp
@@ -310,7 +310,7 @@ TEST_CASE("Search_BadResponse_UnsupportedPackageMatchFields", "[RestSource][Inte
})delimiter");
HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) };
- Interface v1_1{ TestRestUriString, GetTestSourceInformation(), {}, std::move(helper) };
+ Interface v1_1{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {} };
AppInstaller::Repository::SearchRequest request;
PackageMatchFilter filter{ PackageMatchField::Name, MatchType::Exact, "Foo" };
request.Filters.emplace_back(std::move(filter));
@@ -326,7 +326,7 @@ TEST_CASE("Search_BadResponse_RequiredPackageMatchFields", "[RestSource][Interfa
})delimiter");
HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) };
- Interface v1_1{ TestRestUriString, GetTestSourceInformation(), {}, std::move(helper) };
+ Interface v1_1{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {} };
AppInstaller::Repository::SearchRequest request;
PackageMatchFilter filter{ PackageMatchField::Name, MatchType::Exact, "Foo" };
request.Filters.emplace_back(std::move(filter));
@@ -342,7 +342,7 @@ TEST_CASE("GetManifests_BadResponse_UnsupportedQueryParameters", "[RestSource][I
})delimiter");
HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) };
- Interface v1_1{ TestRestUriString, GetTestSourceInformation(), {}, std::move(helper) };
+ Interface v1_1{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {} };
REQUIRE_THROWS_HR(v1_1.GetManifests("Foo"), APPINSTALLER_CLI_ERROR_UNSUPPORTED_SOURCE_REQUEST);
}
@@ -355,7 +355,7 @@ TEST_CASE("GetManifests_BadResponse_RequiredQueryParameters", "[RestSource][Inte
})delimiter");
HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) };
- Interface v1_1{ TestRestUriString, GetTestSourceInformation(), {}, std::move(helper) };
+ Interface v1_1{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {} };
REQUIRE_THROWS_HR(v1_1.GetManifests("Foo"), APPINSTALLER_CLI_ERROR_UNSUPPORTED_SOURCE_REQUEST);
}
@@ -375,7 +375,7 @@ TEST_CASE("Search_BadRequest_UnsupportedPackageMatchFields", "[RestSource][Inter
})delimiter");
HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) };
- Interface v1_1{ TestRestUriString, GetTestSourceInformation(), {}, std::move(helper) };
+ Interface v1_1{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {} };
AppInstaller::Repository::SearchRequest request;
PackageMatchFilter filter{ PackageMatchField::Moniker, MatchType::Exact, "Foo" };
request.Filters.emplace_back(std::move(filter));
@@ -398,7 +398,7 @@ TEST_CASE("Search_GoodRequest_OnlyMarketRequired", "[RestSource][Interface_1_1]"
})delimiter");
HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) };
- Interface v1_1{ TestRestUriString, GetTestSourceInformation(), {}, std::move(helper) };
+ Interface v1_1{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {} };
AppInstaller::Repository::SearchRequest request;
PackageMatchFilter filter{ PackageMatchField::Name, MatchType::Exact, "Foo" };
request.Filters.emplace_back(std::move(filter));
@@ -443,7 +443,7 @@ TEST_CASE("GetManifests_BadRequest_UnsupportedQueryParameters", "[RestSource][In
})delimiter");
HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) };
- Interface v1_1{ TestRestUriString, GetTestSourceInformation(), {}, std::move(helper) };
+ Interface v1_1{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {} };
REQUIRE_THROWS_HR(v1_1.GetManifestByVersion("Foo", "1.0", "beta"), APPINSTALLER_CLI_ERROR_UNSUPPORTED_SOURCE_REQUEST);
}
@@ -479,7 +479,7 @@ TEST_CASE("GetManifests_GoodRequest_OnlyMarketRequired", "[RestSource][Interface
IRestClient::Information info = GetTestSourceInformation();
info.UnsupportedQueryParameters.clear();
HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) };
- Interface v1_1{ TestRestUriString, info, {}, std::move(helper) };
+ Interface v1_1{ TestRestUriString, std::move(helper), info, {} };
auto manifestResult = v1_1.GetManifestByVersion("Foo", "5.0.0", "");
REQUIRE(manifestResult.has_value());
const Manifest& manifest = manifestResult.value();
@@ -526,7 +526,7 @@ TEST_CASE("GetManifests_GoodResponse_MSStoreType", "[RestSource][Interface_1_1]"
})delimiter");
HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(msstoreInstallerResponse)) };
- Interface v1_1{ TestRestUriString, GetTestSourceInformation(), {}, std::move(helper) };
+ Interface v1_1{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {} };
std::vector manifests = v1_1.GetManifests("Foo.Bar");
REQUIRE(manifests.size() == 1);
@@ -542,7 +542,7 @@ TEST_CASE("GetManifests_GoodResponse_V1_1", "[RestSource][Interface_1_1]")
GoodManifest_AllFields sampleManifest;
utility::string_t sample = sampleManifest.GetSampleManifest_AllFields();
HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) };
- Interface v1_1{ TestRestUriString, {}, {}, std::move(helper) };
+ Interface v1_1{ TestRestUriString, std::move(helper), {} };
std::vector manifests = v1_1.GetManifests("Foo.Bar");
REQUIRE(manifests.size() == 1);
diff --git a/src/AppInstallerCLITests/RestInterface_1_4.cpp b/src/AppInstallerCLITests/RestInterface_1_4.cpp
index a1c3bb7add..e136070c42 100644
--- a/src/AppInstallerCLITests/RestInterface_1_4.cpp
+++ b/src/AppInstallerCLITests/RestInterface_1_4.cpp
@@ -361,7 +361,7 @@ TEST_CASE("GetManifests_GoodResponse_V1_4", "[RestSource][Interface_1_4]")
GoodManifest_AllFields sampleManifest;
utility::string_t sample = sampleManifest.GetSampleManifest_AllFields();
HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) };
- Interface v1_4{ TestRestUriString, {}, {}, std::move(helper) };
+ Interface v1_4{ TestRestUriString, std::move(helper), {} };
std::vector manifests = v1_4.GetManifests("Foo.Bar");
REQUIRE(manifests.size() == 1);
@@ -404,7 +404,7 @@ TEST_CASE("Search_GoodResponse_V1_4", "[RestSource][Interface_1_4]")
})delimiter");
HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) };
- Interface v1_4{ TestRestUriString, {}, {}, std::move(helper) };
+ Interface v1_4{ TestRestUriString, std::move(helper), {} };
Schema::IRestClient::SearchResult searchResponse = v1_4.Search({});
REQUIRE(searchResponse.Matches.size() == 1);
Schema::IRestClient::Package package = searchResponse.Matches.at(0);
diff --git a/src/AppInstallerCLITests/RestInterface_1_5.cpp b/src/AppInstallerCLITests/RestInterface_1_5.cpp
index 69416b2c2e..c1a04dc60d 100644
--- a/src/AppInstallerCLITests/RestInterface_1_5.cpp
+++ b/src/AppInstallerCLITests/RestInterface_1_5.cpp
@@ -387,7 +387,7 @@ TEST_CASE("GetManifests_GoodResponse_V1_5", "[RestSource][Interface_1_5]")
GoodManifest_AllFields sampleManifest;
utility::string_t sample = sampleManifest.GetSampleManifest_AllFields();
HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) };
- Interface v1_5{ TestRestUriString, {}, {}, std::move(helper) };
+ Interface v1_5{ TestRestUriString, std::move(helper), {} };
std::vector manifests = v1_5.GetManifests("Foo.Bar");
REQUIRE(manifests.size() == 1);
diff --git a/src/AppInstallerCLITests/RestInterface_1_6.cpp b/src/AppInstallerCLITests/RestInterface_1_6.cpp
index 0cddd5970c..da1582b69c 100644
--- a/src/AppInstallerCLITests/RestInterface_1_6.cpp
+++ b/src/AppInstallerCLITests/RestInterface_1_6.cpp
@@ -389,7 +389,7 @@ TEST_CASE("GetManifests_GoodResponse_V1_6", "[RestSource][Interface_1_6]")
GoodManifest_AllFields sampleManifest;
utility::string_t sample = sampleManifest.GetSampleManifest_AllFields();
HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) };
- Interface v1_6{ TestRestUriString, {}, {}, std::move(helper) };
+ Interface v1_6{ TestRestUriString, std::move(helper), {} };
std::vector manifests = v1_6.GetManifests("Foo.Bar");
REQUIRE(manifests.size() == 1);
diff --git a/src/AppInstallerCLITests/RestInterface_1_7.cpp b/src/AppInstallerCLITests/RestInterface_1_7.cpp
index e2ca66d9e9..bde849b644 100644
--- a/src/AppInstallerCLITests/RestInterface_1_7.cpp
+++ b/src/AppInstallerCLITests/RestInterface_1_7.cpp
@@ -457,7 +457,7 @@ TEST_CASE("GetManifests_GoodRequest_Authentication", "[RestSource][Interface_1_7
// GetManifest should succeed with expected value.
HttpClientHelper helper{ GetHeaderVerificationHandler(web::http::status_codes::OK, SampleGetManifestResponse, { web::http::header_names::authorization, JSON::GetUtilityString(CreateBearerToken(expectedToken)) }, web::http::status_codes::Unauthorized) };
- Interface v1_7{ TestRestUriString, GetTestSourceInformation(), {}, GetTestAuthenticationArguments(), std::move(helper) };
+ Interface v1_7{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {}, GetTestAuthenticationArguments() };
auto manifestResult = v1_7.GetManifestByVersion("Foo.Bar", "5.0.0", "");
REQUIRE(manifestResult.has_value());
const auto& manifest = manifestResult.value();
@@ -482,7 +482,7 @@ TEST_CASE("GetManifests_BadRequest_AuthenticationFailed", "[RestSource][Interfac
// GetManifest should fail with authentication failure
HttpClientHelper helper{ GetHeaderVerificationHandler(web::http::status_codes::OK, SampleGetManifestResponse, { web::http::header_names::authorization, JSON::GetUtilityString(CreateBearerToken(expectedToken)) }, web::http::status_codes::Unauthorized) };
- Interface v1_7{ TestRestUriString, GetTestSourceInformation(), {}, GetTestAuthenticationArguments(), std::move(helper) };
+ Interface v1_7{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {}, GetTestAuthenticationArguments() };
REQUIRE_THROWS_HR(v1_7.GetManifestByVersion("Foo.Bar", "5.0.0", ""), APPINSTALLER_CLI_ERROR_AUTHENTICATION_FAILED);
}
@@ -504,7 +504,7 @@ TEST_CASE("GetManifests_BadRequest_InvalidAuthenticationToken", "[RestSource][In
// GetManifest should fail with access denied
HttpClientHelper helper{ GetHeaderVerificationHandler(web::http::status_codes::OK, SampleGetManifestResponse, { web::http::header_names::authorization, JSON::GetUtilityString(CreateBearerToken(expectedToken)) }, web::http::status_codes::Unauthorized) };
- Interface v1_7{ TestRestUriString, GetTestSourceInformation(), {}, GetTestAuthenticationArguments(), std::move(helper) };
+ Interface v1_7{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {}, GetTestAuthenticationArguments() };
REQUIRE_THROWS_HR(v1_7.GetManifestByVersion("Foo.Bar", "5.0.0", ""), HTTP_E_STATUS_DENIED);
}
@@ -526,7 +526,7 @@ TEST_CASE("Search_GoodRequest_Authentication", "[RestSource][Interface_1_7]")
// Search should succeed with expected value.
HttpClientHelper helper{ GetHeaderVerificationHandler(web::http::status_codes::OK, SampleSearchResponse, { web::http::header_names::authorization, JSON::GetUtilityString(CreateBearerToken(expectedToken)) }, web::http::status_codes::Unauthorized) };
- Interface v1_7{ TestRestUriString, GetTestSourceInformation(), {}, GetTestAuthenticationArguments(), std::move(helper) };
+ Interface v1_7{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {}, GetTestAuthenticationArguments() };
SearchRequest request;
PackageMatchFilter filter{ PackageMatchField::Name, MatchType::Exact, "package" };
request.Filters.emplace_back(std::move(filter));
@@ -553,7 +553,7 @@ TEST_CASE("Search_BadRequest_AuthenticationFailed", "[RestSource][Interface_1_7]
// Search should fail with authentication failure
HttpClientHelper helper{ GetHeaderVerificationHandler(web::http::status_codes::OK, SampleSearchResponse, { web::http::header_names::authorization, JSON::GetUtilityString(CreateBearerToken(expectedToken)) }, web::http::status_codes::Unauthorized) };
- Interface v1_7{ TestRestUriString, GetTestSourceInformation(), {}, GetTestAuthenticationArguments(), std::move(helper) };
+ Interface v1_7{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {}, GetTestAuthenticationArguments() };
SearchRequest request;
PackageMatchFilter filter{ PackageMatchField::Name, MatchType::Exact, "package" };
request.Filters.emplace_back(std::move(filter));
@@ -578,7 +578,7 @@ TEST_CASE("Search_BadRequest_InvalidAuthenticationToken", "[RestSource][Interfac
// Search should fail with access denied
HttpClientHelper helper{ GetHeaderVerificationHandler(web::http::status_codes::OK, SampleSearchResponse, { web::http::header_names::authorization, JSON::GetUtilityString(CreateBearerToken(expectedToken)) }, web::http::status_codes::Unauthorized) };
- Interface v1_7{ TestRestUriString, GetTestSourceInformation(), {}, GetTestAuthenticationArguments(), std::move(helper) };
+ Interface v1_7{ TestRestUriString, std::move(helper), GetTestSourceInformation(), {}, GetTestAuthenticationArguments() };
SearchRequest request;
PackageMatchFilter filter{ PackageMatchField::Name, MatchType::Exact, "package" };
request.Filters.emplace_back(std::move(filter));
@@ -590,7 +590,7 @@ TEST_CASE("GetManifests_GoodResponse_V1_7", "[RestSource][Interface_1_7]")
GoodManifest_AllFields sampleManifest;
utility::string_t sample = sampleManifest.GetSampleManifest_AllFields();
HttpClientHelper helper{ GetTestRestRequestHandler(web::http::status_codes::OK, std::move(sample)) };
- Interface v1_7{ TestRestUriString, {}, {}, {}, std::move(helper) };
+ Interface v1_7{ TestRestUriString, std::move(helper), {} };
std::vector manifests = v1_7.GetManifests("Foo.Bar");
REQUIRE(manifests.size() == 1);
diff --git a/src/AppInstallerCLITests/TestSettings.h b/src/AppInstallerCLITests/TestSettings.h
index 878264a8c1..7da1a728ef 100644
--- a/src/AppInstallerCLITests/TestSettings.h
+++ b/src/AppInstallerCLITests/TestSettings.h
@@ -22,6 +22,7 @@ namespace TestCommon
const std::wstring BypassCertificatePinningForMicrosoftStoreValueName = L"EnableBypassCertificatePinningForMicrosoftStore";
const std::wstring EnableWindowsPackageManagerCommandLineInterfaces = L"EnableWindowsPackageManagerCommandLineInterfaces";
const std::wstring ConfigurationPolicyValueName = L"EnableWindowsPackageManagerConfiguration";
+ const std::wstring ProxyCommandLineOptionsPolicyValueName = L"EnableWindowsPackageManagerProxyCommandLineOptions";
const std::wstring SourceUpdateIntervalPolicyValueName = L"SourceAutoUpdateInterval";
const std::wstring SourceUpdateIntervalPolicyOldValueName = L"SourceAutoUpdateIntervalInMinutes";
diff --git a/src/AppInstallerCLITests/pch.h b/src/AppInstallerCLITests/pch.h
index fdceff3fea..12cd316374 100644
--- a/src/AppInstallerCLITests/pch.h
+++ b/src/AppInstallerCLITests/pch.h
@@ -19,6 +19,8 @@
#include
#include
#include
+#include
+#include
#include
#include
diff --git a/src/AppInstallerCommonCore/AdminSettings.cpp b/src/AppInstallerCommonCore/AdminSettings.cpp
index 71d0f7ba3b..89a23d64ea 100644
--- a/src/AppInstallerCommonCore/AdminSettings.cpp
+++ b/src/AppInstallerCommonCore/AdminSettings.cpp
@@ -19,6 +19,9 @@ namespace AppInstaller::Settings
constexpr Utility::LocIndView s_AdminSettingsYaml_BypassCertificatePinningForMicrosoftStore = "BypassCertificatePinningForMicrosoftStore"_liv;
constexpr Utility::LocIndView s_AdminSettingsYaml_InstallerHashOverride = "InstallerHashOverride"_liv;
constexpr Utility::LocIndView s_AdminSettingsYaml_LocalArchiveMalwareScanOverride = "LocalArchiveMalwareScanOverride"_liv;
+ constexpr Utility::LocIndView s_AdminSettingsYaml_ProxyCommandLineOptions = "ProxyCommandLineOptions"_liv;
+
+ constexpr Utility::LocIndView s_AdminSettingsYaml_DefaultProxy = "DefaultProxy"_liv;
// Attempts to read a single scalar value from the node.
template
@@ -42,20 +45,30 @@ namespace AppInstaller::Settings
bool BypassCertificatePinningForMicrosoftStore = false;
bool InstallerHashOverride = false;
bool LocalArchiveMalwareScanOverride = false;
+ bool ProxyCommandLineOptions = false;
+
+ std::optional DefaultProxy;
};
struct AdminSettingsInternal
{
AdminSettingsInternal();
- void SetAdminSetting(AdminSetting setting, bool enabled);
+ void SetAdminSetting(BoolAdminSetting setting, bool enabled);
+ void SetAdminSetting(StringAdminSetting setting, const std::optional& value);
- bool GetAdminSettingBoolValue(AdminSetting setting) const;
+ bool GetAdminSettingValue(BoolAdminSetting setting) const;
+ std::optional GetAdminSettingValue(StringAdminSetting setting) const;
private:
void LoadAdminSettings();
[[nodiscard]] bool SaveAdminSettings();
+ // Sets the value of an admin setting using the given function and then saves the changes.
+ // Encapsulates the retry and reload logic.
+ // Stops if the value cannot be set, as indicated by the return value of setValue()
+ void SetAdminSettingAndSave(std::function setValue);
+
Stream m_settingStream;
AdminSettingValues m_settingValues;
};
@@ -65,25 +78,12 @@ namespace AppInstaller::Settings
LoadAdminSettings();
}
- void AdminSettingsInternal::SetAdminSetting(AdminSetting setting, bool enabled)
+ void AdminSettingsInternal::SetAdminSettingAndSave(std::function setValue)
{
for (size_t i = 0; i < 10; ++i)
{
- switch (setting)
+ if (!setValue())
{
- case AdminSetting::LocalManifestFiles:
- m_settingValues.LocalManifestFiles = enabled;
- break;
- case AdminSetting::BypassCertificatePinningForMicrosoftStore:
- m_settingValues.BypassCertificatePinningForMicrosoftStore = enabled;
- break;
- case AdminSetting::InstallerHashOverride:
- m_settingValues.InstallerHashOverride = enabled;
- break;
- case AdminSetting::LocalArchiveMalwareScanOverride:
- m_settingValues.LocalArchiveMalwareScanOverride = enabled;
- break;
- default:
return;
}
@@ -99,23 +99,78 @@ namespace AppInstaller::Settings
THROW_HR_MSG(E_UNEXPECTED, "Too many attempts at SaveAdminSettings");
}
- bool AdminSettingsInternal::GetAdminSettingBoolValue(AdminSetting setting) const
+ void AdminSettingsInternal::SetAdminSetting(BoolAdminSetting setting, bool enabled)
+ {
+ SetAdminSettingAndSave([&]()
+ {
+ switch (setting)
+ {
+ case BoolAdminSetting::LocalManifestFiles:
+ m_settingValues.LocalManifestFiles = enabled;
+ return true;
+ case BoolAdminSetting::BypassCertificatePinningForMicrosoftStore:
+ m_settingValues.BypassCertificatePinningForMicrosoftStore = enabled;
+ return true;
+ case BoolAdminSetting::InstallerHashOverride:
+ m_settingValues.InstallerHashOverride = enabled;
+ return true;
+ case BoolAdminSetting::LocalArchiveMalwareScanOverride:
+ m_settingValues.LocalArchiveMalwareScanOverride = enabled;
+ return true;
+ case BoolAdminSetting::ProxyCommandLineOptions:
+ m_settingValues.ProxyCommandLineOptions = enabled;
+ return true;
+ default:
+ return false;
+ }
+ });
+ }
+
+ void AdminSettingsInternal::SetAdminSetting(StringAdminSetting setting, const std::optional& value)
+ {
+ SetAdminSettingAndSave([&]()
+ {
+ switch (setting)
+ {
+ case StringAdminSetting::DefaultProxy:
+ m_settingValues.DefaultProxy = value;
+ return true;
+ default:
+ return false;
+ }
+ });
+ }
+
+ bool AdminSettingsInternal::GetAdminSettingValue(BoolAdminSetting setting) const
{
switch (setting)
{
- case AdminSetting::LocalManifestFiles:
+ case BoolAdminSetting::LocalManifestFiles:
return m_settingValues.LocalManifestFiles;
- case AdminSetting::BypassCertificatePinningForMicrosoftStore:
+ case BoolAdminSetting::BypassCertificatePinningForMicrosoftStore:
return m_settingValues.BypassCertificatePinningForMicrosoftStore;
- case AdminSetting::InstallerHashOverride:
+ case BoolAdminSetting::InstallerHashOverride:
return m_settingValues.InstallerHashOverride;
- case AdminSetting::LocalArchiveMalwareScanOverride:
+ case BoolAdminSetting::LocalArchiveMalwareScanOverride:
return m_settingValues.LocalArchiveMalwareScanOverride;
+ case BoolAdminSetting::ProxyCommandLineOptions:
+ return m_settingValues.ProxyCommandLineOptions;
default:
return false;
}
}
+ std::optional AdminSettingsInternal::GetAdminSettingValue(StringAdminSetting setting) const
+ {
+ switch (setting)
+ {
+ case StringAdminSetting::DefaultProxy:
+ return m_settingValues.DefaultProxy;
+ default:
+ return std::nullopt;
+ }
+ }
+
void AdminSettingsInternal::LoadAdminSettings()
{
auto stream = m_settingStream.Get();
@@ -154,6 +209,13 @@ namespace AppInstaller::Settings
TryReadScalar(document, s_AdminSettingsYaml_BypassCertificatePinningForMicrosoftStore, m_settingValues.BypassCertificatePinningForMicrosoftStore);
TryReadScalar(document, s_AdminSettingsYaml_InstallerHashOverride, m_settingValues.InstallerHashOverride);
TryReadScalar(document, s_AdminSettingsYaml_LocalArchiveMalwareScanOverride, m_settingValues.LocalArchiveMalwareScanOverride);
+ TryReadScalar(document, s_AdminSettingsYaml_ProxyCommandLineOptions, m_settingValues.ProxyCommandLineOptions);
+
+ std::string defaultProxy;
+ if (TryReadScalar(document, s_AdminSettingsYaml_DefaultProxy, defaultProxy))
+ {
+ m_settingValues.DefaultProxy.emplace(std::move(defaultProxy));
+ }
}
bool AdminSettingsInternal::SaveAdminSettings()
@@ -164,74 +226,128 @@ namespace AppInstaller::Settings
out << YAML::Key << s_AdminSettingsYaml_BypassCertificatePinningForMicrosoftStore << YAML::Value << m_settingValues.BypassCertificatePinningForMicrosoftStore;
out << YAML::Key << s_AdminSettingsYaml_InstallerHashOverride << YAML::Value << m_settingValues.InstallerHashOverride;
out << YAML::Key << s_AdminSettingsYaml_LocalArchiveMalwareScanOverride << YAML::Value << m_settingValues.LocalArchiveMalwareScanOverride;
+ out << YAML::Key << s_AdminSettingsYaml_ProxyCommandLineOptions << YAML::Value << m_settingValues.ProxyCommandLineOptions;
+
+ if (m_settingValues.DefaultProxy)
+ {
+ out << YAML::Key << s_AdminSettingsYaml_DefaultProxy << YAML::Value << m_settingValues.DefaultProxy.value();
+ }
+
out << YAML::EndMap;
return m_settingStream.Set(out.str());
}
+
+ auto GetPolicyStateForSetting(BoolAdminSetting setting)
+ {
+ auto policy = GetAdminSettingPolicy(setting);
+ return GroupPolicies().GetState(policy);
+ }
+
+ std::optional> GetPolicyStateForSetting(StringAdminSetting setting)
+ {
+ switch (setting)
+ {
+ case AppInstaller::Settings::StringAdminSetting::DefaultProxy:
+ return GroupPolicies().GetValueRef();
+ default:
+ return std::nullopt;
+ }
+ }
}
- AdminSetting StringToAdminSetting(std::string_view in)
+ BoolAdminSetting StringToBoolAdminSetting(std::string_view in)
{
- AdminSetting result = AdminSetting::Unknown;
+ BoolAdminSetting result = BoolAdminSetting::Unknown;
if (Utility::CaseInsensitiveEquals(s_AdminSettingsYaml_LocalManifestFiles, in))
{
- result = AdminSetting::LocalManifestFiles;
+ result = BoolAdminSetting::LocalManifestFiles;
}
else if (Utility::CaseInsensitiveEquals(s_AdminSettingsYaml_BypassCertificatePinningForMicrosoftStore, in))
{
- result = AdminSetting::BypassCertificatePinningForMicrosoftStore;
+ result = BoolAdminSetting::BypassCertificatePinningForMicrosoftStore;
}
else if (Utility::CaseInsensitiveEquals(s_AdminSettingsYaml_InstallerHashOverride, in))
{
- result = AdminSetting::InstallerHashOverride;
+ result = BoolAdminSetting::InstallerHashOverride;
}
else if (Utility::CaseInsensitiveEquals(s_AdminSettingsYaml_LocalArchiveMalwareScanOverride, in))
{
- result = AdminSetting::LocalArchiveMalwareScanOverride;
+ result = BoolAdminSetting::LocalArchiveMalwareScanOverride;
+ }
+ else if (Utility::CaseInsensitiveEquals(s_AdminSettingsYaml_ProxyCommandLineOptions, in))
+ {
+ result = BoolAdminSetting::ProxyCommandLineOptions;
+ }
+
+ return result;
+ }
+
+ StringAdminSetting StringToStringAdminSetting(std::string_view in)
+ {
+ StringAdminSetting result = StringAdminSetting::Unknown;
+
+ if (Utility::CaseInsensitiveEquals(s_AdminSettingsYaml_DefaultProxy, in))
+ {
+ result = StringAdminSetting::DefaultProxy;
}
return result;
}
- Utility::LocIndView AdminSettingToString(AdminSetting setting)
+ Utility::LocIndView AdminSettingToString(BoolAdminSetting setting)
{
switch (setting)
{
- case AdminSetting::LocalManifestFiles:
+ case BoolAdminSetting::LocalManifestFiles:
return s_AdminSettingsYaml_LocalManifestFiles;
- case AdminSetting::BypassCertificatePinningForMicrosoftStore:
+ case BoolAdminSetting::BypassCertificatePinningForMicrosoftStore:
return s_AdminSettingsYaml_BypassCertificatePinningForMicrosoftStore;
- case AdminSetting::InstallerHashOverride:
+ case BoolAdminSetting::InstallerHashOverride:
return s_AdminSettingsYaml_InstallerHashOverride;
- case AdminSetting::LocalArchiveMalwareScanOverride:
+ case BoolAdminSetting::LocalArchiveMalwareScanOverride:
return s_AdminSettingsYaml_LocalArchiveMalwareScanOverride;
+ case BoolAdminSetting::ProxyCommandLineOptions:
+ return s_AdminSettingsYaml_ProxyCommandLineOptions;
+ default:
+ return "Unknown"_liv;
+ }
+ }
+
+ Utility::LocIndView AdminSettingToString(StringAdminSetting setting)
+ {
+ switch (setting)
+ {
+ case StringAdminSetting::DefaultProxy:
+ return s_AdminSettingsYaml_DefaultProxy;
default:
return "Unknown"_liv;
}
}
- TogglePolicy::Policy GetAdminSettingPolicy(AdminSetting setting)
+ TogglePolicy::Policy GetAdminSettingPolicy(BoolAdminSetting setting)
{
switch (setting)
{
- case AdminSetting::LocalManifestFiles:
+ case BoolAdminSetting::LocalManifestFiles:
return TogglePolicy::Policy::LocalManifestFiles;
- case AdminSetting::BypassCertificatePinningForMicrosoftStore:
+ case BoolAdminSetting::BypassCertificatePinningForMicrosoftStore:
return TogglePolicy::Policy::BypassCertificatePinningForMicrosoftStore;
- case AdminSetting::InstallerHashOverride:
+ case BoolAdminSetting::InstallerHashOverride:
return TogglePolicy::Policy::HashOverride;
- case AdminSetting::LocalArchiveMalwareScanOverride:
+ case BoolAdminSetting::LocalArchiveMalwareScanOverride:
return TogglePolicy::Policy::LocalArchiveMalwareScanOverride;
+ case BoolAdminSetting::ProxyCommandLineOptions:
+ return TogglePolicy::Policy::ProxyCommandLineOptions;
default:
return TogglePolicy::Policy::None;
}
}
- bool EnableAdminSetting(AdminSetting setting)
+ bool EnableAdminSetting(BoolAdminSetting setting)
{
- auto policy = GetAdminSettingPolicy(setting);
- if (GroupPolicies().GetState(policy) == PolicyState::Disabled)
+ if (GetPolicyStateForSetting(setting) == PolicyState::Disabled)
{
return false;
}
@@ -241,10 +357,9 @@ namespace AppInstaller::Settings
return true;
}
- bool DisableAdminSetting(AdminSetting setting)
+ bool DisableAdminSetting(BoolAdminSetting setting)
{
- auto policy = GetAdminSettingPolicy(setting);
- if (GroupPolicies().GetState(policy) == PolicyState::Enabled)
+ if (GetPolicyStateForSetting(setting) == PolicyState::Enabled)
{
return false;
}
@@ -254,31 +369,64 @@ namespace AppInstaller::Settings
return true;
}
- bool IsAdminSettingEnabled(AdminSetting setting)
+ bool IsAdminSettingEnabled(BoolAdminSetting setting)
{
// Check for a policy that overrides this setting.
- auto policy = GetAdminSettingPolicy(setting);
- auto policyState = GroupPolicies().GetState(policy);
+ auto policyState = GetPolicyStateForSetting(setting);
if (policyState != PolicyState::NotConfigured)
{
return policyState == PolicyState::Enabled;
}
AdminSettingsInternal adminSettingsInternal;
- return adminSettingsInternal.GetAdminSettingBoolValue(setting);
+ return adminSettingsInternal.GetAdminSettingValue(setting);
+ }
+
+ bool SetAdminSetting(StringAdminSetting setting, std::string_view value)
+ {
+ if (GetPolicyStateForSetting(setting))
+ {
+ return false;
+ }
+
+ AdminSettingsInternal adminSettingsInternal;
+ adminSettingsInternal.SetAdminSetting(setting, std::string{ value });
+ return true;
}
- std::vector GetAllAdminSettings()
+ bool ResetAdminSetting(StringAdminSetting setting)
{
- std::vector result;
- using AdminSetting_t = std::underlying_type_t;
+ if (GetPolicyStateForSetting(setting))
+ {
+ return false;
+ }
- // Skip Unknown.
- for (AdminSetting_t i = 1 + static_cast(AdminSetting::Unknown); i < static_cast(AdminSetting::Max); ++i)
+ AdminSettingsInternal adminSettingsInternal;
+ adminSettingsInternal.SetAdminSetting(setting, std::nullopt);
+ return true;
+ }
+
+ std::optional GetAdminSetting(StringAdminSetting setting)
+ {
+ // Check for a policy that overrides this setting.
+ auto policyState = GetPolicyStateForSetting(setting);
+ if (policyState)
{
- result.emplace_back(static_cast(i));;
+ return policyState.value();
}
- return result;
+ AdminSettingsInternal adminSettingsInternal;
+ return adminSettingsInternal.GetAdminSettingValue(setting);
+ }
+
+ std::vector GetAllBoolAdminSettings()
+ {
+ return GetAllSequentialEnumValues(BoolAdminSetting::Unknown);
}
+
+ std::vector GetAllStringAdminSettings()
+ {
+ return GetAllSequentialEnumValues(StringAdminSetting::Unknown);
+ }
+
}
diff --git a/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj b/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj
index 298d81f5e2..f9dbdc9361 100644
--- a/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj
+++ b/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj
@@ -435,6 +435,7 @@
+
@@ -481,6 +482,7 @@
+
diff --git a/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj.filters b/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj.filters
index 85789ca484..ab890bd70f 100644
--- a/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj.filters
+++ b/src/AppInstallerCommonCore/AppInstallerCommonCore.vcxproj.filters
@@ -189,6 +189,9 @@
Public\winget
+
+ Public\winget
+
@@ -338,6 +341,9 @@
Authentication
+
+ Source Files
+
diff --git a/src/AppInstallerCommonCore/Deployment.cpp b/src/AppInstallerCommonCore/Deployment.cpp
index cdd87ea01e..08c5c84b26 100644
--- a/src/AppInstallerCommonCore/Deployment.cpp
+++ b/src/AppInstallerCommonCore/Deployment.cpp
@@ -114,6 +114,7 @@ namespace AppInstaller::Deployment
PackageManager packageManager;
// In the event of a failure we want to ensure that the package is not left on the system.
+ // No need for proxy as Deployment won't use it anyways.
Msix::MsixInfo packageInfo{ uri };
std::wstring packageFullNameWide = packageInfo.GetPackageFullNameWide();
std::string packageFullName = Utility::ConvertToUTF8(packageFullNameWide);
@@ -218,6 +219,7 @@ namespace AppInstaller::Deployment
PackageManager packageManager;
// In the event of a failure we want to ensure that the package is not left on the system.
+ // No need for proxy as Deployment won't use it anyways.
Msix::MsixInfo packageInfo{ uri };
std::wstring packageFullNameWide = packageInfo.GetPackageFullNameWide();
std::string packageFullName = Utility::ConvertToUTF8(packageFullNameWide);
diff --git a/src/AppInstallerCommonCore/Downloader.cpp b/src/AppInstallerCommonCore/Downloader.cpp
index 748cce6de9..4f6098533f 100644
--- a/src/AppInstallerCommonCore/Downloader.cpp
+++ b/src/AppInstallerCommonCore/Downloader.cpp
@@ -9,6 +9,7 @@
#include "Public/AppInstallerLogging.h"
#include "Public/AppInstallerTelemetry.h"
#include "Public/winget/UserSettings.h"
+#include "Public/winget/NetworkSettings.h"
#include "Public/winget/Filesystem.h"
#include "DODownloader.h"
#include "HttpStream/HttpRandomAccessStream.h"
@@ -103,12 +104,29 @@ namespace AppInstaller::Utility
AICLI_LOG(Core, Info, << "WinINet downloading from url: " << url);
auto agentWide = Utility::ConvertToUTF16(Runtime::GetDefaultUserAgent().get());
- wil::unique_hinternet session(InternetOpen(
- agentWide.c_str(),
- INTERNET_OPEN_TYPE_PRECONFIG,
- NULL,
- NULL,
- 0));
+ wil::unique_hinternet session;
+
+ const auto& proxyUri = Network().GetProxyUri();
+ if (proxyUri)
+ {
+ AICLI_LOG(Core, Info, << "Using proxy " << proxyUri.value());
+ session.reset(InternetOpen(
+ agentWide.c_str(),
+ INTERNET_OPEN_TYPE_PROXY,
+ Utility::ConvertToUTF16(proxyUri.value()).c_str(),
+ NULL,
+ 0));
+ }
+ else
+ {
+ session.reset(InternetOpen(
+ agentWide.c_str(),
+ INTERNET_OPEN_TYPE_PRECONFIG,
+ NULL,
+ NULL,
+ 0));
+ }
+
THROW_LAST_ERROR_IF_NULL_MSG(session, "InternetOpen() failed.");
auto urlWide = Utility::ConvertToUTF16(url);
@@ -224,6 +242,7 @@ namespace AppInstaller::Utility
std::map GetHeaders(std::string_view url)
{
+ // TODO: Use proxy info. HttpClient does not support using a custom proxy, only using the system-wide one.
AICLI_LOG(Core, Verbose, << "Retrieving headers from url: " << url);
HttpBaseProtocolFilter filter;
@@ -296,11 +315,7 @@ namespace AppInstaller::Utility
// - WinGetUtil :: Intentionally not using DO at this time
if (type == DownloadType::Installer)
{
- // Determine whether to try DO first or not, as this is the only choice currently supported.
- InstallerDownloader setting = User().Get();
-
- if (setting == InstallerDownloader::Default ||
- setting == InstallerDownloader::DeliveryOptimization)
+ if (Network().GetInstallerDownloader() == InstallerDownloader::DeliveryOptimization)
{
try
{
diff --git a/src/AppInstallerCommonCore/ExperimentalFeature.cpp b/src/AppInstallerCommonCore/ExperimentalFeature.cpp
index 98dd70ce88..d531a36fe8 100644
--- a/src/AppInstallerCommonCore/ExperimentalFeature.cpp
+++ b/src/AppInstallerCommonCore/ExperimentalFeature.cpp
@@ -44,6 +44,8 @@ namespace AppInstaller::Settings
return userSettings.Get();
case ExperimentalFeature::Feature::Configuration03:
return userSettings.Get();
+ case ExperimentalFeature::Feature::Proxy:
+ return userSettings.Get();
default:
THROW_HR(E_UNEXPECTED);
}
@@ -77,6 +79,8 @@ namespace AppInstaller::Settings
return ExperimentalFeature{ "Resume", "resume", "https://aka.ms/winget-settings", Feature::Resume };
case Feature::Configuration03:
return ExperimentalFeature{ "Configuration Schema 0.3", "configuration03", "https://aka.ms/winget-settings", Feature::Configuration03 };
+ case Feature::Proxy:
+ return ExperimentalFeature{ "Proxy", "proxy", "https://aka.ms/winget-settings", Feature::Proxy };
default:
THROW_HR(E_UNEXPECTED);
}
diff --git a/src/AppInstallerCommonCore/HttpStream/HttpClientWrapper.cpp b/src/AppInstallerCommonCore/HttpStream/HttpClientWrapper.cpp
index a9aedbb279..d5e1401965 100644
--- a/src/AppInstallerCommonCore/HttpStream/HttpClientWrapper.cpp
+++ b/src/AppInstallerCommonCore/HttpStream/HttpClientWrapper.cpp
@@ -22,6 +22,7 @@ namespace AppInstaller::Utility::HttpStream
{
std::future> HttpClientWrapper::CreateAsync(const Uri& uri)
{
+ // TODO: Use proxy info. HttpClient does not support using a custom proxy, only using the system-wide one.
std::shared_ptr instance = std::make_shared();
// Use an HTTP filter to disable the default caching behavior and use the Most Recent caching behavior instead
diff --git a/src/AppInstallerCommonCore/HttpStream/HttpRandomAccessStream.h b/src/AppInstallerCommonCore/HttpStream/HttpRandomAccessStream.h
index 6947be6578..0ed2d0c108 100644
--- a/src/AppInstallerCommonCore/HttpStream/HttpRandomAccessStream.h
+++ b/src/AppInstallerCommonCore/HttpStream/HttpRandomAccessStream.h
@@ -19,8 +19,7 @@ namespace AppInstaller::Utility::HttpStream
winrt::Windows::Storage::Streams::IInputStream>
{
public:
- winrt::Windows::Foundation::IAsyncOperation InitializeAsync(
- const winrt::Windows::Foundation::Uri& uri);
+ winrt::Windows::Foundation::IAsyncOperation InitializeAsync(const winrt::Windows::Foundation::Uri& uri);
uint64_t Size() const;
void Size(uint64_t value);
uint64_t Position() const;
diff --git a/src/AppInstallerCommonCore/Manifest/MsixManifestValidation.cpp b/src/AppInstallerCommonCore/Manifest/MsixManifestValidation.cpp
index c838d2e8d8..bd769a4d33 100644
--- a/src/AppInstallerCommonCore/Manifest/MsixManifestValidation.cpp
+++ b/src/AppInstallerCommonCore/Manifest/MsixManifestValidation.cpp
@@ -59,8 +59,8 @@ namespace AppInstaller::Manifest
{
AICLI_LOG(Core, Info, << "Start downloading installer");
auto tempFile = Runtime::GetNewTempFilePath();
- ProgressCallback callback;
- Utility::Download(installerUrl, tempFile, Utility::DownloadType::Installer, callback);
+ ProgressCallback emptyCallback;
+ Utility::Download(installerUrl, tempFile, Utility::DownloadType::Installer, emptyCallback);
m_downloadedInstallers.push_back(tempFile);
return tempFile;
}
diff --git a/src/AppInstallerCommonCore/NetworkSettings.cpp b/src/AppInstallerCommonCore/NetworkSettings.cpp
new file mode 100644
index 0000000000..34ef02d5bf
--- /dev/null
+++ b/src/AppInstallerCommonCore/NetworkSettings.cpp
@@ -0,0 +1,60 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+#include "pch.h"
+#include "winget/NetworkSettings.h"
+#include "winget/AdminSettings.h"
+#include "AppInstallerLogging.h"
+
+namespace AppInstaller::Settings
+{
+ void NetworkSettings::SetProxyUri(const std::optional& proxyUri)
+ {
+ AICLI_LOG(Core, Info, << "Setting proxy");
+
+ if (proxyUri)
+ {
+ m_proxyUri = proxyUri.value();
+ AICLI_LOG(Core, Info, << "New value for proxy is " << m_proxyUri.value());
+ }
+ else
+ {
+ m_proxyUri.reset();
+ AICLI_LOG(Core, Info, << "Proxy will not be used");
+ }
+ }
+
+ InstallerDownloader NetworkSettings::GetInstallerDownloader() const
+ {
+ // The default is DeliveryOptimization.
+ // We only use WinINet if specified by settings, or if we want to use proxy (as DO does not support that)
+ InstallerDownloader setting = User().Get();
+
+ if (setting != InstallerDownloader::WinInet && m_proxyUri)
+ {
+ AICLI_LOG(Core, Info, << "Forcing use of wininet for download as DO does not support proxy");
+ return InstallerDownloader::WinInet;
+ }
+ else // Default or DO
+ {
+ return InstallerDownloader::DeliveryOptimization;
+ }
+ }
+
+ NetworkSettings::NetworkSettings()
+ {
+ // Get the default proxy
+ m_proxyUri = GetAdminSetting(StringAdminSetting::DefaultProxy);
+ AICLI_LOG(Core, Info, << "Default proxy is " << (m_proxyUri ? m_proxyUri.value() : "not set"));
+ }
+
+ NetworkSettings& NetworkSettings::Instance()
+ {
+ static NetworkSettings networkSettings;
+ return networkSettings;
+ }
+
+ NetworkSettings& Network()
+ {
+ return NetworkSettings::Instance();
+ }
+}
\ No newline at end of file
diff --git a/src/AppInstallerCommonCore/Public/AppInstallerDownloader.h b/src/AppInstallerCommonCore/Public/AppInstallerDownloader.h
index c99e10767c..1850a44be6 100644
--- a/src/AppInstallerCommonCore/Public/AppInstallerDownloader.h
+++ b/src/AppInstallerCommonCore/Public/AppInstallerDownloader.h
@@ -4,11 +4,6 @@
#include
#include
-#include
-
-#include
-#include
-
#include
#include
#include