winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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:
Msrc/AppInstallerCLICore/Commands/UpgradeCommand.cpp | 2+-
Msrc/AppInstallerCLICore/ExecutionContext.cpp | 2+-
Msrc/AppInstallerCLICore/ExecutionContext.h | 18++++++++++++++++--
Msrc/AppInstallerCLICore/Workflows/InstallFlow.cpp | 44+++++++++++++++++++++++---------------------
Msrc/AppInstallerCLITests/WorkFlow.cpp | 11+++++++----
Msrc/AppInstallerCommonCore/Deployment.cpp | 36++++++++++++++++++++++++++----------
Msrc/AppInstallerCommonCore/Public/AppInstallerDeployment.h | 8+++++---
Msrc/AppInstallerRepositoryCore/Microsoft/PreIndexedPackageSourceFactory.cpp | 3++-
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)