commit e2e6fa23b69741133adc890c89b8f2d3e0df436d
parent 5ab4b1e414d342e5da4a1cc432bfcc11fb8c5050
Author: yao-msft <50888816+yao-msft@users.noreply.github.com>
Date: Thu, 29 Oct 2020 19:02:11 -0700
Update Smart Screen experience for msix (#627)
Diffstat:
8 files changed, 81 insertions(+), 43 deletions(-)
diff --git a/src/AppInstallerCLICore/Commands/UpgradeCommand.cpp b/src/AppInstallerCLICore/Commands/UpgradeCommand.cpp
@@ -113,7 +113,7 @@ namespace AppInstaller::CLI
void UpgradeCommand::ExecuteInternal(Execution::Context& context) const
{
- WI_SetFlag(context.GetFlags(), Execution::ContextFlag::InstallerExecutionUseUpdate);
+ context.SetFlags(Execution::ContextFlag::InstallerExecutionUseUpdate);
context <<
Workflow::ReportExecutionStage(ExecutionStage::Discovery) <<
diff --git a/src/AppInstallerCLICore/ExecutionContext.cpp b/src/AppInstallerCLICore/ExecutionContext.cpp
@@ -73,7 +73,7 @@ namespace AppInstaller::CLI::Execution
std::unique_ptr<Context> Context::Clone()
{
auto clone = std::make_unique<Context>(Reporter);
- clone->GetFlags() = m_flags;
+ clone->m_flags = m_flags;
return clone;
}
diff --git a/src/AppInstallerCLICore/ExecutionContext.h b/src/AppInstallerCLICore/ExecutionContext.h
@@ -64,6 +64,8 @@ namespace AppInstaller::CLI::Execution
{
None = 0x0,
InstallerExecutionUseUpdate = 0x1,
+ InstallerHashMatched = 0x2,
+ InstallerTrusted = 0x4,
};
DEFINE_ENUM_FLAG_OPERATORS(ContextFlag);
@@ -227,12 +229,24 @@ namespace AppInstaller::CLI::Execution
return std::get<details::DataIndex(D)>(itr->second);
}
- // Gets context flags; which can be modified in place.
- ContextFlag& GetFlags()
+ // Gets context flags
+ ContextFlag GetFlags() const
{
return m_flags;
}
+ // Set context flags
+ void SetFlags(ContextFlag flags)
+ {
+ WI_SetAllFlags(m_flags, flags);
+ }
+
+ // Clear context flags
+ void ClearFlags(ContextFlag flags)
+ {
+ WI_ClearAllFlags(m_flags, flags);
+ }
+
#ifndef AICLI_DISABLE_TEST_HOOKS
// Enable tests to override behavior
virtual bool ShouldExecuteWorkflowTask(const Workflow::WorkflowTask&) { return true; }
diff --git a/src/AppInstallerCLICore/Workflows/InstallFlow.cpp b/src/AppInstallerCLICore/Workflows/InstallFlow.cpp
@@ -68,17 +68,17 @@ namespace AppInstaller::CLI::Workflow
case ManifestInstaller::InstallerTypeEnum::Msi:
case ManifestInstaller::InstallerTypeEnum::Nullsoft:
case ManifestInstaller::InstallerTypeEnum::Wix:
- context << DownloadInstallerFile << VerifyInstallerHash;
+ context << DownloadInstallerFile << VerifyInstallerHash << UpdateInstallerFileMotwIfApplicable;
break;
case ManifestInstaller::InstallerTypeEnum::Msix:
if (installer.SignatureSha256.empty())
{
- context << DownloadInstallerFile << VerifyInstallerHash;
+ context << DownloadInstallerFile << VerifyInstallerHash << UpdateInstallerFileMotwIfApplicable;
}
else
{
// Signature hash provided. No download needed. Just verify signature hash.
- context << GetMsixSignatureHash << VerifyInstallerHash;
+ context << GetMsixSignatureHash << VerifyInstallerHash << UpdateInstallerFileMotwIfApplicable;
}
break;
case ManifestInstaller::InstallerTypeEnum::MSStore:
@@ -87,8 +87,6 @@ namespace AppInstaller::CLI::Workflow
default:
THROW_HR(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED));
}
-
- context << UpdateInstallerFileMotwIfApplicable;
}
void DownloadInstallerFile(Execution::Context& context)
@@ -189,6 +187,15 @@ namespace AppInstaller::CLI::Workflow
{
AICLI_LOG(CLI, Info, << "Installer hash verified");
context.Reporter.Info() << Resource::String::InstallerHashVerified << std::endl;
+
+ context.SetFlags(Execution::ContextFlag::InstallerHashMatched);
+
+ if (context.Contains(Execution::Data::PackageVersion) &&
+ context.Get<Execution::Data::PackageVersion>()->GetSource() != nullptr &&
+ SourceTrustLevel::Trusted == context.Get<Execution::Data::PackageVersion>()->GetSource()->GetDetails().TrustLevel)
+ {
+ context.SetFlags(Execution::ContextFlag::InstallerTrusted);
+ }
}
}
@@ -196,21 +203,14 @@ namespace AppInstaller::CLI::Workflow
{
if (context.Contains(Execution::Data::InstallerPath))
{
- // Only update Motw if installer hash matches
- const auto& hashPair = context.Get<Execution::Data::HashPair>();
- if (std::equal(hashPair.first.begin(), hashPair.first.end(), hashPair.second.begin()))
+ if (WI_IsFlagSet(context.GetFlags(), Execution::ContextFlag::InstallerTrusted))
+ {
+ Utility::ApplyMotwIfApplicable(context.Get<Execution::Data::InstallerPath>(), URLZONE_TRUSTED);
+ }
+ else if (WI_IsFlagSet(context.GetFlags(), Execution::ContextFlag::InstallerHashMatched))
{
- if (context.Contains(Execution::Data::PackageVersion) &&
- context.Get<Execution::Data::PackageVersion>()->GetSource() != nullptr &&
- SourceTrustLevel::Trusted == context.Get<Execution::Data::PackageVersion>()->GetSource()->GetDetails().TrustLevel)
- {
- Utility::ApplyMotwIfApplicable(context.Get<Execution::Data::InstallerPath>(), URLZONE_TRUSTED);
- }
- else
- {
- const auto& installer = context.Get<Execution::Data::Installer>();
- Utility::ApplyMotwUsingIAttachmentExecuteIfApplicable(context.Get<Execution::Data::InstallerPath>(), installer.value().Url);
- }
+ const auto& installer = context.Get<Execution::Data::Installer>();
+ Utility::ApplyMotwUsingIAttachmentExecuteIfApplicable(context.Get<Execution::Data::InstallerPath>(), installer.value().Url);
}
}
}
@@ -232,7 +232,7 @@ namespace AppInstaller::CLI::Workflow
if (isUpdate && installer.UpdateBehavior == ManifestInstaller::UpdateBehaviorEnum::UninstallPrevious)
{
// TODO: hook up with uninstall when uninstall is implemented
- WI_ClearFlag(context.GetFlags(), Execution::ContextFlag::InstallerExecutionUseUpdate);
+ context.ClearFlags(Execution::ContextFlag::InstallerExecutionUseUpdate);
AICLI_TERMINATE_CONTEXT(HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED));
}
context << ShellExecuteInstall;
@@ -278,7 +278,9 @@ namespace AppInstaller::CLI::Workflow
DeploymentOptions deploymentOptions =
DeploymentOptions::ForceApplicationShutdown |
DeploymentOptions::ForceTargetApplicationShutdown;
- context.Reporter.ExecuteWithProgress(std::bind(Deployment::RequestAddPackage, uri, deploymentOptions, std::placeholders::_1));
+
+ context.Reporter.ExecuteWithProgress(std::bind(Deployment::AddPackage, uri, deploymentOptions,
+ WI_IsFlagSet(context.GetFlags(), Execution::ContextFlag::InstallerTrusted), std::placeholders::_1));
}
catch (const wil::ResultException& re)
{
diff --git a/src/AppInstallerCLITests/WorkFlow.cpp b/src/AppInstallerCLITests/WorkFlow.cpp
@@ -255,7 +255,7 @@ namespace
std::unique_ptr<Context> Clone() override
{
auto clone = std::make_unique<TestContext>(m_out, m_in, m_overrides);
- clone->GetFlags() = this->GetFlags();
+ clone->SetFlags(this->GetFlags());
return clone;
}
@@ -952,7 +952,7 @@ void VerifyMotw(const std::filesystem::path& testFile, DWORD zone)
REQUIRE(motwContentStr.find("ZoneId=" + std::to_string(zone)) != std::string::npos);
}
-TEST_CASE("UpdateInstallerFileMotw", "[DownloadInstaller][workflow]")
+TEST_CASE("VerifyInstallerTrustLevelAndUpdateInstallerFileMotw", "[DownloadInstaller][workflow]")
{
TestCommon::TempFile testInstallerPath("TestInstaller.txt");
@@ -976,11 +976,14 @@ TEST_CASE("UpdateInstallerFileMotw", "[DownloadInstaller][workflow]")
installer.Url = "http://NotTrusted.com";
context.Add<Data::Installer>(std::move(installer));
- UpdateInstallerFileMotwIfApplicable(context);
+ context << VerifyInstallerHash << UpdateInstallerFileMotwIfApplicable;
+ REQUIRE(WI_IsFlagSet(context.GetFlags(), ContextFlag::InstallerTrusted));
VerifyMotw(testInstallerPath, 2);
testSource->Details.TrustLevel = SourceTrustLevel::None;
- UpdateInstallerFileMotwIfApplicable(context);
+ context.ClearFlags(ContextFlag::InstallerTrusted);
+ context << VerifyInstallerHash << UpdateInstallerFileMotwIfApplicable;
+ REQUIRE_FALSE(WI_IsFlagSet(context.GetFlags(), ContextFlag::InstallerTrusted));
VerifyMotw(testInstallerPath, 3);
INFO(updateMotwOutput.str());
diff --git a/src/AppInstallerCommonCore/Deployment.cpp b/src/AppInstallerCommonCore/Deployment.cpp
@@ -56,24 +56,40 @@ namespace AppInstaller::Deployment
}
}
- void RequestAddPackage(
+ void AddPackage(
const winrt::Windows::Foundation::Uri& uri,
winrt::Windows::Management::Deployment::DeploymentOptions options,
+ bool skipSmartScreen,
IProgressCallback& callback)
{
size_t id = GetDeploymentOperationId();
- AICLI_LOG(Core, Info, << "Starting RequestAddPackage operation #" << id << ": " << Utility::ConvertToUTF8(uri.AbsoluteUri().c_str()));
+ AICLI_LOG(Core, Info, << "Starting AddPackage operation #" << id << ": " << Utility::ConvertToUTF8(uri.AbsoluteUri().c_str()) << "SkipSmartScreen: " << skipSmartScreen);
PackageManager packageManager;
- // RequestAddPackageAsync will invoke smart screen.
- auto deployOperation = packageManager.RequestAddPackageAsync(
- uri,
- nullptr, /*dependencyPackageUris*/
- options,
- nullptr, /*targetVolume*/
- nullptr, /*optionalAndRelatedPackageFamilyNames*/
- nullptr /*relatedPackageUris*/);
+ IAsyncOperationWithProgress<DeploymentResult, DeploymentProgress> deployOperation;
+
+ if (skipSmartScreen)
+ {
+ deployOperation = packageManager.AddPackageAsync(
+ uri,
+ nullptr, /*dependencyPackageUris*/
+ options,
+ nullptr, /*targetVolume*/
+ nullptr, /*optionalAndRelatedPackageFamilyNames*/
+ nullptr, /*optionalPackageUris*/
+ nullptr /*relatedPackageUris*/);
+ }
+ else
+ {
+ deployOperation = packageManager.RequestAddPackageAsync(
+ uri,
+ nullptr, /*dependencyPackageUris*/
+ options,
+ nullptr, /*targetVolume*/
+ nullptr, /*optionalAndRelatedPackageFamilyNames*/
+ nullptr /*relatedPackageUris*/);
+ }
WaitForDeployment(deployOperation, id, callback);
}
diff --git a/src/AppInstallerCommonCore/Public/AppInstallerDeployment.h b/src/AppInstallerCommonCore/Public/AppInstallerDeployment.h
@@ -7,10 +7,12 @@
namespace AppInstaller::Deployment
{
- // Calls winrt::Windows::Management::Deployment::PackageManager::RequestAddPackageAsync
- void RequestAddPackage(
- const winrt::Windows::Foundation::Uri& uri,
+ // Calls winrt::Windows::Management::Deployment::PackageManager::AddPackageAsync if skipSmartScreen is true,
+ // Otherwise, calls winrt::Windows::Management::Deployment::PackageManager::RequestAddPackageAsync
+ void AddPackage(
+ const winrt::Windows::Foundation::Uri& uri,
winrt::Windows::Management::Deployment::DeploymentOptions options,
+ bool skipSmartScreen,
IProgressCallback& callback);
// Calls winrt::Windows::Management::Deployment::PackageManager::RemovePackageAsync
diff --git a/src/AppInstallerRepositoryCore/Microsoft/PreIndexedPackageSourceFactory.cpp b/src/AppInstallerRepositoryCore/Microsoft/PreIndexedPackageSourceFactory.cpp
@@ -198,9 +198,10 @@ namespace AppInstaller::Repository::Microsoft
uri = winrt::Windows::Foundation::Uri(Utility::ConvertToUTF16(packageLocation));
}
- Deployment::RequestAddPackage(
+ Deployment::AddPackage(
uri,
winrt::Windows::Management::Deployment::DeploymentOptions::None,
+ SourceTrustLevel::Trusted == details.TrustLevel,
progress);
if (download)