Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deploy Main and Singleton in BreakAway process when Deployment API is called from MediumILHigherIL Non-Microsoft publisher package #2454

Merged
merged 3 commits into from
May 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions WindowsAppRuntime.sln
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test_BootstrapAutoInitializ
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test_BootstrapAutoInitialize_CS_Options_None", "test\DynamicDependency\Test_BootstrapAutoInitialize\CS\Test_BootstrapAutoInitialize_CS_Options_None\Test_BootstrapAutoInitialize_CS_Options_None.csproj", "{4A74BBED-3B20-44A7-B6FF-3373160DE741}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DeploymentAgent", "dev\DeploymentAgent\DeploymentAgent.vcxproj", "{4410D374-A90C-4ADF-8B15-AA2AAE2636BF}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
test\inc\inc.vcxitems*{08bc78e0-63c6-49a7-81b3-6afc3deac4de}*SharedItemsImports = 4
Expand Down Expand Up @@ -1332,6 +1334,22 @@ Global
{4A74BBED-3B20-44A7-B6FF-3373160DE741}.Release|x64.Build.0 = Release|x64
{4A74BBED-3B20-44A7-B6FF-3373160DE741}.Release|x86.ActiveCfg = Release|x86
{4A74BBED-3B20-44A7-B6FF-3373160DE741}.Release|x86.Build.0 = Release|x86
{4410D374-A90C-4ADF-8B15-AA2AAE2636BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4410D374-A90C-4ADF-8B15-AA2AAE2636BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4410D374-A90C-4ADF-8B15-AA2AAE2636BF}.Debug|ARM64.ActiveCfg = Debug|arm64
{4410D374-A90C-4ADF-8B15-AA2AAE2636BF}.Debug|ARM64.Build.0 = Debug|arm64
{4410D374-A90C-4ADF-8B15-AA2AAE2636BF}.Debug|x64.ActiveCfg = Debug|x64
{4410D374-A90C-4ADF-8B15-AA2AAE2636BF}.Debug|x64.Build.0 = Debug|x64
{4410D374-A90C-4ADF-8B15-AA2AAE2636BF}.Debug|x86.ActiveCfg = Debug|x86
{4410D374-A90C-4ADF-8B15-AA2AAE2636BF}.Debug|x86.Build.0 = Debug|x86
{4410D374-A90C-4ADF-8B15-AA2AAE2636BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4410D374-A90C-4ADF-8B15-AA2AAE2636BF}.Release|Any CPU.Build.0 = Release|Any CPU
{4410D374-A90C-4ADF-8B15-AA2AAE2636BF}.Release|ARM64.ActiveCfg = Release|arm64
{4410D374-A90C-4ADF-8B15-AA2AAE2636BF}.Release|ARM64.Build.0 = Release|arm64
{4410D374-A90C-4ADF-8B15-AA2AAE2636BF}.Release|x64.ActiveCfg = Release|x64
{4410D374-A90C-4ADF-8B15-AA2AAE2636BF}.Release|x64.Build.0 = Release|x64
{4410D374-A90C-4ADF-8B15-AA2AAE2636BF}.Release|x86.ActiveCfg = Release|x86
{4410D374-A90C-4ADF-8B15-AA2AAE2636BF}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -1445,6 +1463,7 @@ Global
{0EF1080B-15C6-42E7-A0E2-D624D85C3EBF} = {99C514E4-A6B3-4B09-B870-5511EF9D93AC}
{D9139E3C-8D21-4BD9-84E3-30A03A54D610} = {99C514E4-A6B3-4B09-B870-5511EF9D93AC}
{4A74BBED-3B20-44A7-B6FF-3373160DE741} = {99C514E4-A6B3-4B09-B870-5511EF9D93AC}
{4410D374-A90C-4ADF-8B15-AA2AAE2636BF} = {E378857C-D22A-4E5E-A6DA-A59C445CF22E}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4B3D7591-CFEC-4762-9A07-ABE99938FB77}
Expand Down
2 changes: 2 additions & 0 deletions build/CopyFilesToStagingDir.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\StrippedWinMD\Microsoft.Windo
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\MsixDynamicDependency.h $FullPublishDir\Microsoft.WindowsAppRuntime\
PublishFile $FullBuildOutput\WindowsAppRuntime_DLL\wil_msixdynamicdependency.h $FullPublishDir\Microsoft.WindowsAppRuntime\
PublishFile $FullBuildOutput\RestartAgent\RestartAgent.exe $FullPublishDir\Microsoft.WindowsAppRuntime\
PublishFile $FullBuildOutput\DeploymentAgent\DeploymentAgent.exe $FullPublishDir\Microsoft.WindowsAppRuntime\

#
PublishFile $FullBuildOutput\DynamicDependency.DataStore\DynamicDependency.DataStore.exe $FullPublishDir\DynamicDependency.DataStore\
Expand Down Expand Up @@ -76,6 +77,7 @@ PublishFile $FullBuildOutput\DynamicDependencyLifetimeManager\DynamicDependencyL
PublishFile $FullBuildOutput\DynamicDependencyLifetimeManagerShadow\DynamicDependencyLifetimeManagerShadow.pdb $symbolsOutputDir
PublishFile $FullBuildOutput\WindowsAppRuntime_BootstrapDLL\Microsoft.WindowsAppRuntime.Bootstrap.pdb $symbolsOutputDir
PublishFile $FullBuildOutput\RestartAgent\RestartAgent.pdb $symbolsOutputDir
PublishFile $FullBuildOutput\DeploymentAgent\DeploymentAgent.pdb $symbolsOutputDir

# Copy files to Full Nuget package (alphabetical by category)
#
Expand Down
11 changes: 11 additions & 0 deletions dev/Deployment/DeploymentActivityContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ namespace WindowsAppRuntime::Deployment::Activity
GUID m_deploymentErrorActivityId{};
WindowsAppRuntimeDeployment_TraceLogger::Initialize m_activity;
WilFailure m_lastFailure;
bool isFullTrustPackage{};

public:
static WindowsAppRuntime::Deployment::Activity::Context& Get();
Expand Down Expand Up @@ -77,6 +78,11 @@ namespace WindowsAppRuntime::Deployment::Activity
return m_lastFailure;
}

const bool& GetIsFullTrustPackage()
sachintaMSFT marked this conversation as resolved.
Show resolved Hide resolved
{
return isFullTrustPackage;
}

void SetInstallStage(const DeploymentStage& installStage)
{
m_installStage = installStage;
Expand All @@ -103,6 +109,11 @@ namespace WindowsAppRuntime::Deployment::Activity
}

void SetLastFailure(const wil::FailureInfo& failure);

void SetIsFullTrustPackage()
{
isFullTrustPackage = true;
}
};

static WindowsAppRuntime::Deployment::Activity::Context g_DeploymentActivityContext;
Expand Down
153 changes: 120 additions & 33 deletions dev/Deployment/DeploymentManager.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

#include <pch.h>
#include <DeploymentManager.h>
#include <DeploymentResult.h>
Expand All @@ -14,19 +15,25 @@
using namespace winrt;
using namespace Windows::Foundation;

#define Initialize_StopSuccessActivity() initializeActivityContext.GetActivity().StopWithResult(\
S_OK,\
static_cast <UINT32>(0),\
static_cast<PCSTR>(nullptr),\
static_cast <unsigned int>(0),\
static_cast<PCWSTR>(nullptr),\
static_cast<PCSTR>(nullptr),\
static_cast <UINT32>(getStatusResult.Status()),\
static_cast<UINT32>(::WindowsAppRuntime::Deployment::Activity::DeploymentStage::None),\
static_cast<PCWSTR>(nullptr),\
S_OK,\
static_cast<PCWSTR>(nullptr),\
GUID_NULL);
inline void Initialize_StopSuccessActivity(
::WindowsAppRuntime::Deployment::Activity::Context& initializeActivityContext,
const winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::DeploymentStatus& deploymentStatus)
{
initializeActivityContext.GetActivity().StopWithResult(
S_OK,
static_cast <UINT32>(0),
static_cast<PCSTR>(nullptr),
static_cast <unsigned int>(0),
static_cast<PCWSTR>(nullptr),
static_cast<PCSTR>(nullptr),
static_cast <UINT32>(deploymentStatus),
static_cast<UINT32>(::WindowsAppRuntime::Deployment::Activity::DeploymentStage::None),
static_cast<PCWSTR>(nullptr),
S_OK,
static_cast<PCWSTR>(nullptr),
GUID{},
::WindowsAppRuntime::Deployment::Activity::Context::Get().GetIsFullTrustPackage());
}

namespace winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implementation
{
Expand All @@ -39,15 +46,21 @@ namespace winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implem

winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::DeploymentResult DeploymentManager::Initialize()
{
::WindowsAppRuntime::Deployment::Activity::Context::Get().GetActivity().Start(false, Security::IntegrityLevel::IsElevated());
::WindowsAppRuntime::Deployment::Activity::Context::Get().GetActivity().Start(false,
Security::IntegrityLevel::IsElevated(),
AppModel::Identity::IsPackagedProcess(),
Security::IntegrityLevel::GetIntegrityLevel());

FAIL_FAST_HR_IF(HRESULT_FROM_WIN32(APPMODEL_ERROR_NO_PACKAGE), !AppModel::Identity::IsPackagedProcess());
return Initialize(GetCurrentFrameworkPackageFullName());
}

winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::DeploymentResult DeploymentManager::Initialize(winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::DeploymentInitializeOptions const& deploymentInitializeOptions)
{
::WindowsAppRuntime::Deployment::Activity::Context::Get().GetActivity().Start(deploymentInitializeOptions.ForceDeployment(), Security::IntegrityLevel::IsElevated());
::WindowsAppRuntime::Deployment::Activity::Context::Get().GetActivity().Start(deploymentInitializeOptions.ForceDeployment(),
Security::IntegrityLevel::IsElevated(),
AppModel::Identity::IsPackagedProcess(),
Security::IntegrityLevel::GetIntegrityLevel());

FAIL_FAST_HR_IF(HRESULT_FROM_WIN32(APPMODEL_ERROR_NO_PACKAGE), !AppModel::Identity::IsPackagedProcess());
return Initialize(GetCurrentFrameworkPackageFullName(), deploymentInitializeOptions);
Expand Down Expand Up @@ -141,7 +154,7 @@ namespace winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implem
auto getStatusResult{ DeploymentManager::GetStatus(packageFullName) };
if (getStatusResult.Status() == DeploymentStatus::Ok)
{
Initialize_StopSuccessActivity();
Initialize_StopSuccessActivity(initializeActivityContext, getStatusResult.Status());
return getStatusResult;
}

Expand All @@ -151,7 +164,7 @@ namespace winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implem
if (SUCCEEDED(deployPackagesResult))
{
status = DeploymentStatus::Ok;
Initialize_StopSuccessActivity();
Initialize_StopSuccessActivity(initializeActivityContext, status);
}
else
{
Expand All @@ -169,7 +182,8 @@ namespace winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implem
initializeActivityContext.GetCurrentResourceId().c_str(),
initializeActivityContext.GetDeploymentErrorExtendedHResult(),
initializeActivityContext.GetDeploymentErrorText().c_str(),
initializeActivityContext.GetDeploymentErrorActivityId());
initializeActivityContext.GetDeploymentErrorActivityId(),
initializeActivityContext.GetIsFullTrustPackage());
}

return winrt::make<implementation::DeploymentResult>(status, deployPackagesResult);
Expand Down Expand Up @@ -251,26 +265,22 @@ namespace winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implem
THROW_WIN32(rc);
}

auto path = wil::make_process_heap_string(nullptr, pathLength);
auto path{ wil::make_process_heap_string(nullptr, pathLength) };
THROW_IF_WIN32_ERROR(GetPackagePathByFullName(packageFullName.c_str(), &pathLength, path.get()));
return std::wstring(path.get());
return std::wstring{ path.get() };
}

// Adds the package at the path using PackageManager.
// This requires the 'packageManagement' or 'runFullTrust' capabilities.
HRESULT DeploymentManager::AddPackage(const std::filesystem::path& packagePath, bool forceDeployment) try
HRESULT DeploymentManager::AddPackage(const std::filesystem::path& packagePath, const bool forceDeployment) try
{
winrt::Windows::Management::Deployment::PackageManager packageManager;

auto GetDeploymentOptions = [](bool forceDeployment)
{
return (forceDeployment ?
winrt::Windows::Management::Deployment::DeploymentOptions::ForceTargetApplicationShutdown :
winrt::Windows::Management::Deployment::DeploymentOptions::None);
};
const auto options{ forceDeployment ?
winrt::Windows::Management::Deployment::DeploymentOptions::ForceTargetApplicationShutdown :
winrt::Windows::Management::Deployment::DeploymentOptions::None };

const auto options{ GetDeploymentOptions(forceDeployment) };
const auto packagePathUri = winrt::Windows::Foundation::Uri(packagePath.c_str());
const auto packagePathUri{ winrt::Windows::Foundation::Uri(packagePath.c_str()) };
const auto deploymentOperation{ packageManager.AddPackageAsync(packagePathUri, nullptr, options) };
deploymentOperation.get();
const auto deploymentResult{ deploymentOperation.GetResults() };
Expand All @@ -289,8 +299,76 @@ namespace winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implem
}
CATCH_RETURN()


std::wstring DeploymentManager::GenerateDeploymentAgentPath()
{
// Calculate the path to the restart agent as being in the same directory as the current module.
wil::unique_hmodule module;
THROW_IF_WIN32_BOOL_FALSE(GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, reinterpret_cast<PCWSTR>(DeploymentManager::GenerateDeploymentAgentPath), &module));

std::filesystem::path modulePath{ wil::GetModuleFileNameW<std::wstring>(module.get()) };
return modulePath.parent_path() / c_deploymentAgentFilename;
}

HRESULT DeploymentManager::AddPackageInBreakAwayProcess(const std::filesystem::path& packagePath, const bool forceDeployment) try
{
auto exePath{ GenerateDeploymentAgentPath() };
auto activityId{ winrt::to_hstring(*::WindowsAppRuntime::Deployment::Activity::Context::Get().GetActivity().Id()) };

// <currentdirectory>\deploymentagent.exe <custom arguments passed by caller>
auto cmdLine{ wil::str_printf<wil::unique_cotaskmem_string>(L"\"%s\" \"%s\" % s % s", exePath.c_str(), packagePath.c_str(), forceDeployment, activityId.c_str()) };

SIZE_T attributeListSize{};
auto attributeCount{ 1 };

if (AppModel::Identity::IsPackagedProcess())
{
// Packaged scenarios have an additional attribute.
attributeCount++;
}

THROW_IF_WIN32_BOOL_FALSE(InitializeProcThreadAttributeList(nullptr, attributeCount, 0, &attributeListSize));
PPROC_THREAD_ATTRIBUTE_LIST attributeList = reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>(new BYTE[attributeListSize]);
THROW_IF_WIN32_BOOL_FALSE(InitializeProcThreadAttributeList(attributeList, attributeCount, 0, &attributeListSize));
auto freeAttributeList{ wil::scope_exit([&] { DeleteProcThreadAttributeList(attributeList); }) };

// Launch the deployment agent
THROW_IF_WIN32_BOOL_FALSE(UpdateProcThreadAttribute(attributeList, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, nullptr, 0, nullptr, nullptr));

if (AppModel::Identity::IsPackagedProcess())
{
// Desktop Bridge applications by default have their child processes break away from the parent process. In order to recreate the calling process'
// environment correctly, this code must prevent child breakaway semantics when calling the agent. Additionally the agent must do the same when
// restarting the caller.
DWORD policy{ PROCESS_CREATION_DESKTOP_APP_BREAKAWAY_OVERRIDE };
THROW_IF_WIN32_BOOL_FALSE(UpdateProcThreadAttribute(attributeList, 0, PROC_THREAD_ATTRIBUTE_DESKTOP_APP_POLICY, &policy, sizeof(policy), nullptr, nullptr));
}

STARTUPINFOEX info{};
info.StartupInfo.cb = sizeof(info);
info.lpAttributeList = attributeList;

wil::unique_process_information processInfo;
THROW_IF_WIN32_BOOL_FALSE(CreateProcess(nullptr, cmdLine.get(), nullptr, nullptr, TRUE, CREATE_SUSPENDED | EXTENDED_STARTUPINFO_PRESENT, nullptr, nullptr,
&info.StartupInfo, &processInfo));

// Transfer foreground rights to the new process before resuming it.
AllowSetForegroundWindow(processInfo.dwProcessId);
ResumeThread(processInfo.hThread);

// This API is designed to only return to the caller on failure, otherwise block until process termination.
// Wait for the agent to exit. If the agent succeeds, it will terminate this process. If the agent fails,
// it can exit or crash. This API will be able to detect the failure and return.
wil::handle_wait(processInfo.hProcess);

DWORD processExitCode{};
THROW_IF_WIN32_BOOL_FALSE_MSG(GetExitCodeProcess(processInfo.hProcess, &processExitCode), "CmdLine: %ls, processExitCode: %lu", cmdLine.get(), processExitCode);
return S_OK;
}
CATCH_RETURN()

// Deploys all of the packages carried by the specified framework.
HRESULT DeploymentManager::Deploy(const std::wstring& frameworkPackageFullName, bool forceDeployment) try
HRESULT DeploymentManager::Deploy(const std::wstring& frameworkPackageFullName, const bool forceDeployment) try
{
RETURN_IF_FAILED(InstallLicenses(frameworkPackageFullName));
RETURN_IF_FAILED(DeployPackages(frameworkPackageFullName, forceDeployment));
Expand Down Expand Up @@ -344,7 +422,7 @@ namespace winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implem
return S_OK;
}

HRESULT DeploymentManager::DeployPackages(const std::wstring& frameworkPackageFullName, bool forceDeployment)
HRESULT DeploymentManager::DeployPackages(const std::wstring& frameworkPackageFullName, const bool forceDeployment)
{
::WindowsAppRuntime::Deployment::Activity::Context::Get().SetInstallStage(::WindowsAppRuntime::Deployment::Activity::DeploymentStage::GetPackagePath);
const auto frameworkPath{ std::filesystem::path(GetPackagePath(frameworkPackageFullName)) };
Expand All @@ -359,8 +437,17 @@ namespace winrt::Microsoft::Windows::ApplicationModel::WindowsAppRuntime::implem
packagePath /= WINDOWSAPPRUNTIME_FRAMEWORK_PACKAGE_FOLDER;
packagePath /= package.identifier + WINDOWSAPPRUNTIME_FRAMEWORK_PACKAGE_FILE_EXTENSION;

// Deploy package.
RETURN_IF_FAILED(AddPackage(packagePath, forceDeployment));
if (AppModel::Identity::IsPackagedProcess() &&
Security::IntegrityLevel::GetIntegrityLevel() >= SECURITY_MANDATORY_MEDIUM_RID)
{
::WindowsAppRuntime::Deployment::Activity::Context::Get().SetIsFullTrustPackage();
RETURN_IF_FAILED(AddPackageInBreakAwayProcess(packagePath, forceDeployment));
}
else
{
// Deploy package.
RETURN_IF_FAILED(AddPackage(packagePath, forceDeployment));
}

// Restart Push Notifications Long Running Platform when ForceDeployment option is applied.
if (forceDeployment &&
Expand Down
Loading