Skip to content

Commit

Permalink
KozaniHostRuntime implementation and FTA and protocol launch support (#…
Browse files Browse the repository at this point in the history
…3714)

* not sure the state of things (#3612) (#3613)

Co-authored-by: William Cheng <wcheng@ntdev.microsoft.com>

* Initial integration

1. Enabled RDC launch to the foreground.
2. Hook up wil logging to trace providers
3. Added KozaniHostRuntime to KozaniManager MSIX package.

* HostRuntime integration and FTA impl

* FTA launch done - Fixed ref count bugs and added proper cleanup for failure cases.

* Implemented FTA and protocol launch support in KozaniRemoteManager

* Fixed error code issue

* Use app extension to store remote app AUMID

* Addressed CR feedbacks.

* Fixed build issue in x86 and ARM64

---------

Co-authored-by: William Cheng <wcheng@ntdev.microsoft.com>
  • Loading branch information
rhuang-msft and William Cheng committed Aug 4, 2023
1 parent 3cd6f77 commit d82f92c
Show file tree
Hide file tree
Showing 46 changed files with 1,479 additions and 236 deletions.
4 changes: 2 additions & 2 deletions WindowsAppRuntime.sln
Original file line number Diff line number Diff line change
Expand Up @@ -2147,8 +2147,8 @@ Global
{FD0CC14A-ED4B-4936-B68B-F31E58372E32}.Release|ARM64.Build.0 = Release|x64
{FD0CC14A-ED4B-4936-B68B-F31E58372E32}.Release|x64.ActiveCfg = Release|x64
{FD0CC14A-ED4B-4936-B68B-F31E58372E32}.Release|x64.Build.0 = Release|x64
{FD0CC14A-ED4B-4936-B68B-F31E58372E32}.Release|x86.ActiveCfg = Release|Any CPU
{FD0CC14A-ED4B-4936-B68B-F31E58372E32}.Release|x86.Build.0 = Release|Any CPU
{FD0CC14A-ED4B-4936-B68B-F31E58372E32}.Release|x86.ActiveCfg = Release|x64
{FD0CC14A-ED4B-4936-B68B-F31E58372E32}.Release|x86.Build.0 = Release|x64
{4B4667B2-94DB-4A19-8270-0FDB1676C27B}.Debug|Any CPU.ActiveCfg = Debug|x64
{4B4667B2-94DB-4A19-8270-0FDB1676C27B}.Debug|Any CPU.Build.0 = Debug|x64
{4B4667B2-94DB-4A19-8270-0FDB1676C27B}.Debug|ARM64.ActiveCfg = Debug|ARM64
Expand Down
1 change: 1 addition & 0 deletions dev/Common/Common.vcxitems
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@
<ClInclude Include="$(MSBuildThisFileDirectory)Security.IntegrityLevel.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)WindowsAppRuntime.SelfContained.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)WindowsAppRuntime.VersionInfo.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)winrt_WindowsAppRuntime.h" />
</ItemGroup>
</Project>
3 changes: 3 additions & 0 deletions dev/Common/Common.vcxitems.filters
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
<ClInclude Include="$(MSBuildThisFileDirectory)Microsoft.RoApi.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)winrt_WindowsAppRuntime.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(MSBuildThisFileDirectory)WindowsAppRuntime.SelfContained.cpp">
Expand Down
33 changes: 33 additions & 0 deletions dev/Common/winrt_WindowsAppRuntime.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (c) Microsoft Corporation and Contributors.
// Licensed under the MIT License.

#ifndef __WINRT_WINDOWS_APP_RUNTIME_H
#define __WINRT_WINDOWS_APP_RUNTIME_H

namespace winrt
{
// Per https://docs.microsoft.com/windows/uwp/cpp-and-winrt-apis/interop-winrt-abi#convert_from_abi-function
template <typename T>
T convert_from_abi(::IUnknown* from)
{
T to{ nullptr }; // `T` is a projected type.

winrt::check_hresult(from->QueryInterface(winrt::guid_of<T>(),
winrt::put_abi(to)));

return to;
}

template <typename T>
T convert_from_abi(::IInspectable* from)
{
T to{ nullptr }; // `T` is a projected type.

winrt::check_hresult(from->QueryInterface(winrt::guid_of<T>(),
winrt::put_abi(to)));

return to;
}
}

#endif // __WINRT_WINDOWS_APP_RUNTIME_H
2 changes: 1 addition & 1 deletion dev/DynamicDependency/API/DataStore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
#include "DataStore.h"

#include "DynamicDependencyDataStore_h.h"
#include "winrt_msixdynamicdependency.h"
#include "winrt_WindowsAppRuntime.h"

#include <wil/winrt.h>

Expand Down
3 changes: 1 addition & 2 deletions dev/DynamicDependency/API/DynamicDependency.vcxitems
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@
<ClInclude Include="$(MSBuildThisFileDirectory)WinRTInprocModule.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)WinRTModuleManager.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)WinRTPackage.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)winrt_msixdynamicdependency.h" />
<ClInclude Include="$(MSBuildThisFileDirectory)winrt_namespaces.h" />
</ItemGroup>
<ItemGroup>
Expand All @@ -74,4 +73,4 @@
<PublicHeaders Include="$(MSBuildThisFileDirectory)..\..\common\TerminalVelocityFeatures-DynamicDependency.h" />
<PublicHeaders Include="$(MSBuildThisFileDirectory)wil_msixdynamicdependency.h" />
</ItemGroup>
</Project>
</Project>
5 changes: 1 addition & 4 deletions dev/DynamicDependency/API/DynamicDependency.vcxitems.filters
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,8 @@
<ClInclude Include="$(MSBuildThisFileDirectory)appmodel_packageinfo.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="$(MSBuildThisFileDirectory)winrt_msixdynamicdependency.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Midl Include="$(MSBuildThisFileDirectory)M.AM.DynamicDependency.idl" />
</ItemGroup>
</Project>
</Project>
19 changes: 0 additions & 19 deletions dev/DynamicDependency/API/winrt_msixdynamicdependency.h

This file was deleted.

2 changes: 0 additions & 2 deletions dev/Kozani/Common/KozaniDvc-Constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,4 @@
namespace Microsoft::Kozani::DVC::Constants
{
const char ConnectionIdSwitch[] = "-connectionId";

const WCHAR RemoteDesktopClientExe[] = L"mstsc.exe";
}
74 changes: 44 additions & 30 deletions dev/Kozani/Common/KozaniDvcProtocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,15 @@
// Licensed under the MIT License.

#include <pch.h>
#include <winrt\Windows.Storage.h>
#include "KozaniDvcProtocol.h"

namespace Microsoft::Kozani::DvcProtocol
{
bool IsEmptyPayloadProtocolDataUnitType(Dvc::ProtocolDataUnit::DataType type)
std::string CreatePdu(UINT64 activityId, Dvc::ProtocolDataUnit::DataType type, const std::string& payload)
{
switch (type)
{
case Dvc::ProtocolDataUnit::AppTerminationNotice:
return true;
}

return false;
}

std::string CreatePdu(UINT64 activityId, Dvc::ProtocolDataUnit::DataType type, const std::string& payload = std::string())
{
if (!IsEmptyPayloadProtocolDataUnitType(type))
{
// Payload data of the Pdu should not be empty. It catches a failure condition when empty string is returned
// from a failed SerializeAsString call before calling into this method.
THROW_HR_IF(KOZANI_E_PDU_SERIALIZATION, payload.empty());
}

// Do not check payload.empty() because if the payload message only contains default values, it can be empty after SerializeAsString().

Dvc::ProtocolDataUnit pdu;
pdu.set_activity_id(activityId);
pdu.set_type(type);
Expand All @@ -36,8 +21,9 @@ namespace Microsoft::Kozani::DvcProtocol
}

std::string rawPdu{ pdu.SerializeAsString() };
THROW_HR_IF(KOZANI_E_PDU_SERIALIZATION, rawPdu.empty());

// rawPdu should never be empty as the activityId must not be default value (0).
THROW_HR_IF(KOZANI_E_PDU_SERIALIZATION, rawPdu.empty());
return rawPdu;
}

Expand All @@ -53,15 +39,43 @@ namespace Microsoft::Kozani::DvcProtocol
switch (args.Kind())
{
case winrt::Windows::ApplicationModel::Activation::ActivationKind::Launch:
auto specificArgs{ args.as<winrt::Windows::ApplicationModel::Activation::LaunchActivatedEventArgs>() };
if (!specificArgs.Arguments().empty())
{
const std::string argsUtf8{ ::Microsoft::Utf8::ToUtf8(specificArgs.Arguments().c_str()) };
Dvc::LaunchActivationArgs launchArgs;
launchArgs.set_arguments(std::move(argsUtf8));
return launchArgs.SerializeAsString();
auto specificArgs{ args.as<winrt::Windows::ApplicationModel::Activation::LaunchActivatedEventArgs>() };
if (!specificArgs.Arguments().empty())
{
const std::string argsUtf8{ ::Microsoft::Utf8::ToUtf8(specificArgs.Arguments().c_str()) };
Dvc::LaunchActivationArgs launchArgs;
launchArgs.set_arguments(std::move(argsUtf8));
return launchArgs.SerializeAsString();
}
break;
}

case winrt::Windows::ApplicationModel::Activation::ActivationKind::File:
{
auto specificArgs{ args.as<winrt::Windows::ApplicationModel::Activation::FileActivatedEventArgs>() };
const std::string verbUtf8{ ::Microsoft::Utf8::ToUtf8(specificArgs.Verb().c_str()) };
Dvc::FileActivationArgs fileArgs;
fileArgs.set_verb(std::move(verbUtf8));

auto files{ specificArgs.Files() };
for (auto const& file : specificArgs.Files())
{
const std::string filePathUtf8{ ::Microsoft::Utf8::ToUtf8(file.Path().c_str()) };
fileArgs.add_file_paths(std::move(filePathUtf8));
}

return fileArgs.SerializeAsString();
}
case winrt::Windows::ApplicationModel::Activation::ActivationKind::Protocol:
{
auto specificArgs{ args.as<winrt::Windows::ApplicationModel::Activation::ProtocolActivatedEventArgs>() };
const std::string uriUtf8{ ::Microsoft::Utf8::ToUtf8(specificArgs.Uri().AbsoluteUri().c_str())};
Dvc::ProtocolActivationArgs protocolArgs;
protocolArgs.set_uri(std::move(uriUtf8));

return protocolArgs.SerializeAsString();
}
break;
}
return std::string();
}
Expand All @@ -70,16 +84,16 @@ namespace Microsoft::Kozani::DvcProtocol
UINT64 activityId,
PCWSTR appUserModelId,
winrt::Windows::ApplicationModel::Activation::ActivationKind activationKind,
winrt::Windows::ApplicationModel::Activation::IActivatedEventArgs& args)
const std::string& serializedArgs)
{
Dvc::ActivateAppRequest activateAppRequest;
activateAppRequest.set_activation_kind(static_cast<Dvc::ActivationKind>(activationKind));

const std::string appUserModelIdUtf8{ ::Microsoft::Utf8::ToUtf8(appUserModelId) };
activateAppRequest.set_app_user_model_id(std::move(appUserModelIdUtf8));
if (args)
if (!serializedArgs.empty())
{
activateAppRequest.set_arguments(SerializeActivatedEventArgs(args));
activateAppRequest.set_arguments(serializedArgs);
}

return CreatePdu(activityId, Dvc::ProtocolDataUnit::ActivateAppRequest, activateAppRequest.SerializeAsString());
Expand Down
5 changes: 3 additions & 2 deletions dev/Kozani/Common/KozaniDvcProtocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#pragma once

#include <Windows.ApplicationModel.Activation.h>
#include <winrt/Windows.ApplicationModel.Activation.h>
#include <Microsoft.Utf8.h>
#include <Kozani.DVC.pb.h>
Expand All @@ -13,7 +14,7 @@ namespace Microsoft::Kozani::DvcProtocol
{
const char DvcChannelName[] = "KozaniDvc";

std::string CreatePdu(UINT64 activityId, Dvc::ProtocolDataUnit::DataType type, const std::string& payload);
std::string CreatePdu(UINT64 activityId, Dvc::ProtocolDataUnit::DataType type, const std::string& payload = std::string());

std::string CreateConnectionAckPdu(PCSTR connectionId, UINT64 activityId);

Expand All @@ -23,7 +24,7 @@ namespace Microsoft::Kozani::DvcProtocol
UINT64 activityId,
PCWSTR appUserModelId,
winrt::Windows::ApplicationModel::Activation::ActivationKind activationKind,
winrt::Windows::ApplicationModel::Activation::IActivatedEventArgs& args);
const std::string& serializedArgs);

std::string CreateActivateAppResultPdu(
UINT64 activityId,
Expand Down
50 changes: 47 additions & 3 deletions dev/Kozani/Common/Logging.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
// According to https://learn.microsoft.com/en-us/windows/win32/com/codes-in-facility-itf, all the COM-defined FACILITY_ITF codes have a code value
// in the range of 0x0000-0x01FF. It is recommended that only code values in the range of 0x0200-0xFFFF be used for 3rd party FACILITY_ITF codes.

// Success HRESULT used for Kozani information logging purpose.
// 0x00040201 (262657)
constexpr HRESULT KOZANI_S_INFO{ MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_ITF, 0x0201) };
// HRESULT used for Kozani information logging purpose. Note that it does NOT mean there is an error. WIL logging requires a failure HRESULT as the input
// to the LOG_HR_MSG() macro. Passing in a successful HRESULT to the macro will cause fail fast crash in Debug build, or it will log XS_STATUS_ASSERTION_FAILURE
// in released build. So it has to be a failure HRESULT, although it does not mean failure in this case.
// 0x80040201 (-2147220991)
constexpr HRESULT KOZANI_E_INFO{ MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0201) };

// Bad/malformatted PDU that cannot be parsed successfully.
// 0x80040202 (-2147220990)
Expand All @@ -22,3 +24,45 @@ constexpr HRESULT KOZANI_E_UNSUPPORTED_ACTIVATION_KIND{ MAKE_HRESULT(SEVERITY_ER
// Bad/malformatted PDU that cannot be parsed successfully.
// 0x80040204 (-2147220988)
constexpr HRESULT KOZANI_E_PDU_SERIALIZATION{ MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0204) };

#if RESULT_DIAGNOSTICS_LEVEL > 3

#define TRACELOGGING_FAILURE_CONTEXT(failure) \
TraceLoggingHResult(failure.hr, "HResult"), \
TraceLoggingString(failure.pszFile, "File"), \
TraceLoggingUInt32(failure.uLineNumber, "LineNumber"), \
TraceLoggingString(failure.pszFunction, "Function"), \
TraceLoggingWideString(failure.pszMessage, "Message"), \
TraceLoggingString(failure.pszCallContext, "CallingContext"), \
TraceLoggingString(failure.pszModule, "Module"), \
TraceLoggingPointer(failure.returnAddress, "Site"), \
TraceLoggingString(failure.pszCode, "Code") \

#else

#define TRACELOGGING_FAILURE_CONTEXT(failure) \
TraceLoggingHResult(failure.hr, "HResult"), \
TraceLoggingString(failure.pszFile, "File"), \
TraceLoggingUInt32(failure.uLineNumber, "LineNumber"), \
TraceLoggingWideString(failure.pszMessage, "Message") \

#endif

template<typename TProvider>
void __stdcall TraceFailureFromProvider(const wil::FailureInfo& failure) WI_NOEXCEPT
{
if (failure.hr == KOZANI_E_INFO)
{
TraceLoggingWrite(
TProvider::Provider(),
"Info",
TRACELOGGING_FAILURE_CONTEXT(failure));
}
else
{
TraceLoggingWrite(
TProvider::Provider(),
"Failure",
TRACELOGGING_FAILURE_CONTEXT(failure));
}
}
9 changes: 7 additions & 2 deletions dev/Kozani/KozaniHostRuntime/KozaniHostRuntime.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>(MSBuildThisFileDirectory);$(OutDir)\..\WindowsAppRuntime_DLL;$(RepoRoot)\dev\WindowsAppRuntime_Insights;$(RepoRoot)\dev\common;$(IntDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>(MSBuildThisFileDirectory);$(OutDir)\..\WindowsAppRuntime_DLL;$(RepoRoot)\dev\WindowsAppRuntime_Insights;$(RepoRoot)\dev\common;$(IntDir);$(OutDir)..\KozaniManagerProxyStub;$(RepoRoot)\dev\Kozani\common;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
<PreprocessorDefinitions>KOZANIHOSTRUNTIMEDLL_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
Expand Down Expand Up @@ -186,6 +186,11 @@
<AdditionalIncludeDirectories>$(RepoRoot)\dev\Common;$(RepoRoot);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\KozaniManagerRuntime\KozaniManagerRuntime.vcxproj">
<Project>{400ed5ec-4530-4adb-8dce-9d1e6708a1f5}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
<Import Project="$(NugetPackageDirectory)\Microsoft.Windows.CppWinRT.$(MicrosoftWindowsCppWinRTVersion)\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('$(NugetPackageDirectory)\Microsoft.Windows.CppWinRT.$(MicrosoftWindowsCppWinRTVersion)\build\native\Microsoft.Windows.CppWinRT.targets')" />
Expand All @@ -208,4 +213,4 @@
<Error Condition="!Exists('$(NugetPackageDirectory)\Microsoft.SourceLink.GitHub.$(MicrosoftSourceLinkGitHubVersion)\build\Microsoft.SourceLink.GitHub.props')" Text="$([System.String]::Format('$(ErrorText)', '$(NugetPackageDirectory)\Microsoft.SourceLink.GitHub.$(MicrosoftSourceLinkGitHubVersion)\build\Microsoft.SourceLink.GitHub.props'))" />
<Error Condition="!Exists('$(NugetPackageDirectory)\Microsoft.SourceLink.GitHub.$(MicrosoftSourceLinkGitHubVersion)\build\Microsoft.SourceLink.GitHub.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(NugetPackageDirectory)\Microsoft.SourceLink.GitHub.$(MicrosoftSourceLinkGitHubVersion)\build\Microsoft.SourceLink.GitHub.targets'))" />
</Target>
</Project>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
<ClInclude Include="KozaniHostRuntimeTraceLogging.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="KozaniHostRuntimeActivity.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
Expand Down Expand Up @@ -59,4 +62,7 @@
<Filter>Resource Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>
<ItemGroup>
<Natvis Include="$(MSBuildThisFileDirectory)..\..\natvis\wil.natvis" />
</ItemGroup>
</Project>
2 changes: 2 additions & 0 deletions dev/Kozani/KozaniHostRuntime/framework.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@
#include <winrt/Windows.Foundation.Collections.h>

#include <winrt/Windows.ApplicationModel.h>
#include <winrt/Windows.ApplicationModel.Activation.h>
#include <winrt/Windows.ApplicationModel.AppExtensions.h>
#include <winrt/Windows.Management.Deployment.h>
#include <winrt/Windows.Storage.h>

#include <appmodel.identity.h>
#include <security.integritylevel.h>
Expand Down
Loading

0 comments on commit d82f92c

Please sign in to comment.