Wire up passing LNK/EXE data from OpenCon to ITerminalHandoff (#13570)

This PR by itself doesn't _really_ change much. Technically, now the Terminal will respect the Title of a `.lnk` when started for defterm, but we don't do anything else yet. Primarily, the goal of this PR is to just wire up startup info in OpenConsole to the connected Terminal. 
* This required a bit of changes in `srvinit.cpp:ConsoleEstablishHandoff` to replicate other bits of startup, where we crack open the connect message to get the relevant bits of info.
* We pack that all into a `TERMINAL_STARTUP_INFO`, which we pass along to the registered terminal application.
* `ConptyConnection` accepts the handoff, and gathers that information out of the `TERMINAL_STARTUP_INFO`
* Some other updates to the scratch sln were made to make it build again (related, but unimportant).
* This is a precursor to:
  * #13111
  * #12154
* Closes #9458
* Tested manually
* I work here
This commit is contained in:
Mike Griese 2022-08-26 06:16:29 -05:00 committed by GitHub
parent deb5e7c650
commit 7e47f6aab9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 254 additions and 45 deletions

View File

@ -17,9 +17,15 @@
<DisableEmbeddedXbf>false</DisableEmbeddedXbf>
<XamlComponentResourceLocation>nested</XamlComponentResourceLocation>
</PropertyGroup>
<PropertyGroup Label="NuGet Dependencies">
<TerminalCppWinrt>true</TerminalCppWinrt>
<TerminalXamlApplicationToolkit>true</TerminalXamlApplicationToolkit>
</PropertyGroup>
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)src\common.nugetversions.props" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
<ItemDefinitionGroup>
<ClCompile>
@ -147,14 +153,15 @@
<!-- ========================= Globals ======================== -->
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
<!-- This -must- go after cppwinrt.build.post.props because that includes many VS-provided props including appcontainer.common.props, which stomps on what cppwinrt.targets did. -->
<Import Project="$(OpenConsoleDir)src\common.nugetversions.targets" />
<Import Project="$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets'))" />
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
<Error Condition="!Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets'))" />
</Target>
<!--

View File

@ -11,9 +11,13 @@
<!-- sets a bunch of Windows Universal properties -->
<OpenConsoleUniversalApp>true</OpenConsoleUniversalApp>
</PropertyGroup>
<PropertyGroup Label="NuGet Dependencies">
<TerminalCppWinrt>true</TerminalCppWinrt>
<TerminalXamlApplicationToolkit>true</TerminalXamlApplicationToolkit>
</PropertyGroup>
<Import Project="..\..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)src\common.nugetversions.props" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
<Import Project="$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
<!-- ========================= XAML files ======================== -->
<ItemGroup>
<!-- DON'T PUT XAML FILES HERE! Put them in SampleAppLib.vcxproj -->
@ -79,15 +83,20 @@
</Reference>
</ItemGroup>
<!-- ====================== Compiler & Linker Flags ===================== -->
<ItemDefinitionGroup>
<Link>
<AdditionalDependencies>$(OpenConsoleCommonOutDir)\ConTypes.lib;WindowsApp.lib;shell32.lib;user32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<Import Project="$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" />
<Import Project="$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('$(OpenConsoleDir)packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets'))" />
<Error Condition="!Exists('$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(OpenConsoleDir)\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
</Target>
<ItemDefinitionGroup>
@ -102,4 +111,7 @@
</Link>
</ItemDefinitionGroup>
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
<!-- This -must- go after cppwinrt.build.post.props because that includes many VS-provided props including appcontainer.common.props, which stomps on what cppwinrt.targets did. -->
<Import Project="$(OpenConsoleDir)src\common.nugetversions.targets" />
</Project>

View File

@ -104,8 +104,6 @@ void SampleIslandWindow::_HandleCreateWindow(const WPARAM, const LPARAM lParam)
void SampleIslandWindow::Initialize()
{
const bool initialized = (_interopWindowHandle != nullptr);
_source = DesktopWindowXamlSource{};
auto interop = _source.as<IDesktopWindowXamlSourceNative>();

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
<PropertyGroup Label="Globals">
<ProjectGuid>{b4427499-9fde-4208-b456-5bc580637633}</ProjectGuid>
@ -16,7 +15,15 @@
<TargetPlatformIdentifier>Windows</TargetPlatformIdentifier>
</PropertyGroup>
<PropertyGroup Label="NuGet Dependencies">
<TerminalCppWinrt>true</TerminalCppWinrt>
<TerminalXamlApplicationToolkit>true</TerminalXamlApplicationToolkit>
<TerminalVCRTForwarders>true</TerminalVCRTForwarders>
<TerminalThemeHelpers>true</TerminalThemeHelpers>
</PropertyGroup>
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<Import Project="$(OpenConsoleDir)src\common.nugetversions.props" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
<ItemDefinitionGroup>
@ -138,16 +145,11 @@
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
<Import Project="..\..\..\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
<Import Project="..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets" Condition="Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.7.1\build\native\Microsoft.UI.Xaml.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.4\build\native\Microsoft.VCRTForwarders.140.targets'))" />
</Target>
<!-- Override GetPackagingOutputs to roll up all our dependencies.
@ -225,13 +227,24 @@
<TargetPath>%(Filename)%(Extension)</TargetPath>
</PackagingOutputs>
</ItemGroup>
<!-- Same thing AGAIN here, with OpenConsole.exe If you forget this, then
the scratch app will use the inbox conpty with a newer conpty lib, causing
us to send the inbox conhost messages that will make it explode. -->
<ItemGroup>
<_OpenConsoleExe Include="$(OpenConsoleCommonOutDir)\OpenConsole.exe" />
<PackagingOutputs Include="@(_OpenConsoleExe)">
<ProjectName>$(ProjectName)</ProjectName>
<OutputGroup>BuiltProjectOutputGroup</OutputGroup>
<TargetPath>%(Filename)%(Extension)</TargetPath>
</PackagingOutputs>
</ItemGroup>
</Target>
<Import Project="$(OpenConsoleDir)\build\rules\GenerateSxsManifestsFromWinmds.targets" />
<Import Project="..\..\..\packages\Terminal.ThemeHelpers.0.2.200324001\build\native\Terminal.ThemeHelpers.targets" Condition="Exists('..\..\..\packages\Terminal.ThemeHelpers.0.2.200324001\build\native\Terminal.ThemeHelpers.targets')" />
<!-- This -must- go after cppwinrt.build.post.props because that includes many VS-provided props including appcontainer.common.props, which stomps on what cppwinrt.targets did. -->
<Import Project="$(OpenConsoleDir)src\common.nugetversions.targets" />
</Project>

View File

@ -99,7 +99,8 @@
<com:ComInterface>
<com:ProxyStub Id="DEC4804D-56D1-4F73-9FBE-6828E7C85C56" DisplayName="OpenConsoleHandoffProxy" Path="OpenConsoleProxy.dll"/>
<com:Interface Id="E686C757-9A35-4A1C-B3CE-0BCC8B5C69F4" ProxyStubClsid="DEC4804D-56D1-4F73-9FBE-6828E7C85C56"/>
<com:Interface Id="59D55CCE-FC8A-48B4-ACE8-0A9286C6557F" ProxyStubClsid="DEC4804D-56D1-4F73-9FBE-6828E7C85C56"/>
<com:Interface Id="59D55CCE-FC8A-48B4-ACE8-0A9286C6557F" ProxyStubClsid="DEC4804D-56D1-4F73-9FBE-6828E7C85C56"/> <!-- ITerminalHandoff -->
<com:Interface Id="AA6B364F-4A50-4176-9002-0AE755E7B5EF" ProxyStubClsid="DEC4804D-56D1-4F73-9FBE-6828E7C85C56"/> <!-- ITerminalHandoff2 -->
<com:Interface Id="746E6BC0-AB05-4E38-AB14-71E86763141F" ProxyStubClsid="DEC4804D-56D1-4F73-9FBE-6828E7C85C56"/>
</com:ComInterface>
</com:Extension>

View File

@ -188,7 +188,8 @@
<com:ComInterface>
<com:ProxyStub Id="1833E661-CC81-4DD0-87C6-C2F74BD39EFA" DisplayName="OpenConsoleHandoffProxy" Path="OpenConsoleProxy.dll"/>
<com:Interface Id="E686C757-9A35-4A1C-B3CE-0BCC8B5C69F4" ProxyStubClsid="1833E661-CC81-4DD0-87C6-C2F74BD39EFA"/>
<com:Interface Id="59D55CCE-FC8A-48B4-ACE8-0A9286C6557F" ProxyStubClsid="1833E661-CC81-4DD0-87C6-C2F74BD39EFA"/>
<com:Interface Id="59D55CCE-FC8A-48B4-ACE8-0A9286C6557F" ProxyStubClsid="1833E661-CC81-4DD0-87C6-C2F74BD39EFA"/> <!-- ITerminalHandoff -->
<com:Interface Id="AA6B364F-4A50-4176-9002-0AE755E7B5EF" ProxyStubClsid="1833E661-CC81-4DD0-87C6-C2F74BD39EFA"/> <!-- ITerminalHandoff2 -->
<com:Interface Id="746E6BC0-AB05-4E38-AB14-71E86763141F" ProxyStubClsid="1833E661-CC81-4DD0-87C6-C2F74BD39EFA"/>
</com:ComInterface>
</com:Extension>

View File

@ -188,7 +188,8 @@
<com:ComInterface>
<com:ProxyStub Id="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F" DisplayName="OpenConsoleHandoffProxy" Path="OpenConsoleProxy.dll"/>
<com:Interface Id="E686C757-9A35-4A1C-B3CE-0BCC8B5C69F4" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/>
<com:Interface Id="59D55CCE-FC8A-48B4-ACE8-0A9286C6557F" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/>
<com:Interface Id="59D55CCE-FC8A-48B4-ACE8-0A9286C6557F" ProxyStubClsid="1833E661-CC81-4DD0-87C6-C2F74BD39EFA"/> <!-- ITerminalHandoff -->
<com:Interface Id="AA6B364F-4A50-4176-9002-0AE755E7B5EF" ProxyStubClsid="1833E661-CC81-4DD0-87C6-C2F74BD39EFA"/> <!-- ITerminalHandoff2 -->
<com:Interface Id="746E6BC0-AB05-4E38-AB14-71E86763141F" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/>
</com:ComInterface>
</com:Extension>

View File

@ -3270,6 +3270,7 @@ namespace winrt::TerminalApp::implementation
{
NewTerminalArgs newTerminalArgs;
newTerminalArgs.Commandline(connection.Commandline());
newTerminalArgs.TabTitle(connection.StartingTitle());
// GH #12370: We absolutely cannot allow a defterm connection to
// auto-elevate. Defterm doesn't work for elevated scenarios in the
// first place. If we try accepting the connection, the spawning an

View File

@ -102,7 +102,7 @@ static HRESULT _duplicateHandle(const HANDLE in, HANDLE& out) noexcept
// - E_NOT_VALID_STATE if a event handler is not registered before calling. `::DuplicateHandle`
// error codes if we cannot manage to make our own copy of handles to retain. Or S_OK/error
// from the registered handler event function.
HRESULT CTerminalHandoff::EstablishPtyHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client)
HRESULT CTerminalHandoff::EstablishPtyHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client, TERMINAL_STARTUP_INFO startupInfo)
{
try
{
@ -132,7 +132,7 @@ HRESULT CTerminalHandoff::EstablishPtyHandoff(HANDLE in, HANDLE out, HANDLE sign
THROW_IF_FAILED(_duplicateHandle(client, client));
// Call registered handler from when we started listening.
THROW_IF_FAILED(localPfnHandoff(in, out, signal, ref, server, client));
THROW_IF_FAILED(localPfnHandoff(in, out, signal, ref, server, client, startupInfo));
#pragma warning(suppress : 26477)
TraceLoggingWrite(

View File

@ -26,10 +26,10 @@ Author(s):
#define __CLSID_CTerminalHandoff "051F34EE-C1FD-4B19-AF75-9BA54648434C"
#endif
using NewHandoffFunction = HRESULT (*)(HANDLE, HANDLE, HANDLE, HANDLE, HANDLE, HANDLE);
using NewHandoffFunction = HRESULT (*)(HANDLE, HANDLE, HANDLE, HANDLE, HANDLE, HANDLE, TERMINAL_STARTUP_INFO);
struct __declspec(uuid(__CLSID_CTerminalHandoff))
CTerminalHandoff : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::RuntimeClassType::ClassicCom>, ITerminalHandoff>
CTerminalHandoff : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::RuntimeClassType::ClassicCom>, ITerminalHandoff2>
{
#pragma region ITerminalHandoff
STDMETHODIMP EstablishPtyHandoff(HANDLE in,
@ -37,7 +37,8 @@ struct __declspec(uuid(__CLSID_CTerminalHandoff))
HANDLE signal,
HANDLE ref,
HANDLE server,
HANDLE client) override;
HANDLE client,
TERMINAL_STARTUP_INFO startupInfo) override;
#pragma endregion

View File

@ -203,7 +203,8 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
const HANDLE hOut,
const HANDLE hRef,
const HANDLE hServerProcess,
const HANDLE hClientProcess) :
const HANDLE hClientProcess,
TERMINAL_STARTUP_INFO startupInfo) :
_initialRows{ 25 },
_initialCols{ 80 },
_guid{ Utils::CreateGuid() },
@ -213,6 +214,12 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
THROW_IF_FAILED(ConptyPackPseudoConsole(hServerProcess, hRef, hSig, &_hPC));
_piClient.hProcess = hClientProcess;
_startupInfo.title = winrt::hstring{ startupInfo.pszTitle, SysStringLen(startupInfo.pszTitle) };
SysFreeString(startupInfo.pszTitle);
_startupInfo.iconPath = winrt::hstring{ startupInfo.pszIconPath, SysStringLen(startupInfo.pszIconPath) };
SysFreeString(startupInfo.pszIconPath);
_startupInfo.iconIndex = startupInfo.iconIndex;
try
{
_commandline = _commandlineFromProcess(hClientProcess);
@ -288,6 +295,11 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
return _commandline;
}
winrt::hstring ConptyConnection::StartingTitle() const
{
return _startupInfo.title;
}
void ConptyConnection::Start()
try
{
@ -667,10 +679,10 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
winrt::event_token ConptyConnection::NewConnection(const NewConnectionHandler& handler) { return _newConnectionHandlers.add(handler); };
void ConptyConnection::NewConnection(const winrt::event_token& token) { _newConnectionHandlers.remove(token); };
HRESULT ConptyConnection::NewHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client) noexcept
HRESULT ConptyConnection::NewHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client, TERMINAL_STARTUP_INFO startupInfo) noexcept
try
{
_newConnectionHandlers(winrt::make<ConptyConnection>(signal, in, out, ref, server, client));
_newConnectionHandlers(winrt::make<ConptyConnection>(signal, in, out, ref, server, client, startupInfo));
return S_OK;
}

View File

@ -8,6 +8,8 @@
#include <conpty-static.h>
#include "ITerminalHandoff.h"
namespace wil
{
// These belong in WIL upstream, so when we reingest the change that has them we'll get rid of ours.
@ -23,7 +25,8 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
const HANDLE hOut,
const HANDLE hRef,
const HANDLE hServerProcess,
const HANDLE hClientProcess);
const HANDLE hClientProcess,
TERMINAL_STARTUP_INFO startupInfo);
ConptyConnection() noexcept = default;
void Initialize(const Windows::Foundation::Collections::ValueSet& settings);
@ -42,6 +45,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
winrt::guid Guid() const noexcept;
winrt::hstring Commandline() const;
winrt::hstring StartingTitle() const;
static void StartInboundListener();
static void StopInboundListener();
@ -60,7 +64,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
WINRT_CALLBACK(TerminalOutput, TerminalOutputHandler);
private:
static HRESULT NewHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client) noexcept;
static HRESULT NewHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client, TERMINAL_STARTUP_INFO startupInfo) noexcept;
static winrt::hstring _commandlineFromProcess(HANDLE process);
HRESULT _LaunchAttachedClient() noexcept;
@ -93,6 +97,14 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
std::array<char, 4096> _buffer{};
bool _passthroughMode{};
struct StartupInfoFromDefTerm
{
winrt::hstring title{};
winrt::hstring iconPath{};
int32_t iconIndex{};
} _startupInfo{};
DWORD _OutputThread();
};
}

View File

@ -12,6 +12,7 @@ namespace Microsoft.Terminal.TerminalConnection
ConptyConnection();
Guid Guid { get; };
String Commandline { get; };
String StartingTitle { get; };
void ClearBuffer();

View File

@ -4,11 +4,41 @@
import "oaidl.idl";
import "ocidl.idl";
typedef struct _TERMINAL_STARTUP_INFO
{
// In STARTUPINFO
BSTR pszTitle;
// Also wanted
BSTR pszIconPath;
LONG iconIndex;
// The rest of STARTUPINFO
DWORD dwX;
DWORD dwY;
DWORD dwXSize;
DWORD dwYSize;
DWORD dwXCountChars;
DWORD dwYCountChars;
DWORD dwFillAttribute;
DWORD dwFlags;
WORD wShowWindow;
} TERMINAL_STARTUP_INFO;
// LOAD BEARING!
//
// There is only ever one OpenConsoleProxy.dll loaded by COM for _ALL_ terminal
// instances, across Dev, Preview, Stable, whatever. So we have to keep all old
// versions of interfaces in the file here, even if the old version is no longer
// in use.
[
object,
uuid(59D55CCE-FC8A-48B4-ACE8-0A9286C6557F)
] interface ITerminalHandoff : IUnknown
{
// DEPRECATED!
HRESULT EstablishPtyHandoff([in, system_handle(sh_pipe)] HANDLE in,
[in, system_handle(sh_pipe)] HANDLE out,
[in, system_handle(sh_pipe)] HANDLE signal,
@ -16,3 +46,17 @@ import "ocidl.idl";
[in, system_handle(sh_process)] HANDLE server,
[in, system_handle(sh_process)] HANDLE client);
};
[
object,
uuid(AA6B364F-4A50-4176-9002-0AE755E7B5EF)
] interface ITerminalHandoff2 : IUnknown
{
HRESULT EstablishPtyHandoff([in, system_handle(sh_pipe)] HANDLE in,
[in, system_handle(sh_pipe)] HANDLE out,
[in, system_handle(sh_pipe)] HANDLE signal,
[in, system_handle(sh_file)] HANDLE ref,
[in, system_handle(sh_process)] HANDLE server,
[in, system_handle(sh_process)] HANDLE client,
[in] TERMINAL_STARTUP_INFO startupInfo);
};

View File

@ -18,6 +18,7 @@
#include "../server/Entrypoints.h"
#include "../server/IoSorter.h"
#include "../interactivity/inc/ISystemConfigurationProvider.hpp"
#include "../interactivity/inc/ServiceLocator.hpp"
#include "../interactivity/base/ApiDetector.hpp"
#include "../interactivity/base/RemoteConsoleControl.hpp"
@ -179,7 +180,7 @@ static bool s_IsOnDesktop()
// We need to see if we were spawned from a link. If we were, we need to
// call back into the shell to try to get all the console information from the link.
ServiceLocator::LocateSystemConfigurationProvider()->GetSettingsFromLink(&settings, Title, &TitleLength, CurDir, AppName);
ServiceLocator::LocateSystemConfigurationProvider()->GetSettingsFromLink(&settings, Title, &TitleLength, CurDir, AppName, nullptr);
// If we weren't started from a link, this will already be set.
// If LoadLinkInfo couldn't find anything, it will remove the flag so we can dig in the registry.
@ -198,6 +199,22 @@ static bool s_IsOnDesktop()
// strong nudge in that direction. If an application _doesn't_ want VT
// processing, it's free to disable this setting, even in conpty mode.
settings.SetVirtTermLevel(1);
// GH#9458 - In the case of a DefTerm handoff, the OriginalTitle might
// be stashed in the lnk. We want to crack that lnk open, so we can get
// that title from it, but we want to discard everything else. So build
// a dummy Settings object here, and read the link settings into it.
// `Title` will get filled with the title from the lnk, which we'll use
// below.
Settings temp;
// We're not gonna copy over StartupFlags to the main gci settings,
// because we generally don't think those are valuable in ConPTY mode.
// However, we do need to apply them to the temp we've created, so that
// GetSettingsFromLink will actually look for the link settings (it will
// skip that if STARTF_TITLEISLINKNAME is not set).
temp.SetStartupFlags(pStartupSettings->GetStartupFlags());
ServiceLocator::LocateSystemConfigurationProvider()->GetSettingsFromLink(&temp, Title, &TitleLength, CurDir, AppName, nullptr);
}
// 1. The settings we were passed contains STARTUPINFO structure settings to be applied last.
@ -494,7 +511,7 @@ try
const auto serverProcess = GetCurrentProcess();
::Microsoft::WRL::ComPtr<ITerminalHandoff> handoff;
::Microsoft::WRL::ComPtr<ITerminalHandoff2> handoff;
TraceLoggingWrite(g_hConhostV2EventTraceProvider,
"SrvInit_PrepareToCreateDelegationTerminal",
@ -509,12 +526,71 @@ try
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
// As a part of defterm handoff, we're gonna try to pull a lot of
// information out of the link and startup info, so we can let the terminal
// know these things as well.
//
// To let the terminal know these things, we have to look them up now,
// before we normally would.
//
// Typically, we'll just go into `ConsoleCreateIoThread` below, which will
// pull out the CONSOLE_API_CONNECTINFO from this connect message, and then
// get the link properties out of the title later. Below are elements of
// ConsoleAllocateConsole and SetUpConsole that get the bits of STARTUP_INFO
// we care about for defterm handoffs.
// A placeholder that we'll read icon information into, instead of setting
// the globals icon state.
Microsoft::Console::Interactivity::IconInfo icon;
// To be able to actually process this connect message into a
// CONSOLE_API_CONNECTINFO, we need to hook up the ConDrvDeviceComm to the
// message. Usually, we'd create the ConDrvDeviceComm later, in
// ConsoleServerInitialization, but we can set it up early here.
// ConsoleServerInitialization will safely no-op if it already finds one.
g.pDeviceComm = new ConDrvDeviceComm(Server);
// load bearing: if you don't set this, the ConsoleInitializeConnectInfo will fail.
connectMessage->_pDeviceComm = g.pDeviceComm;
CONSOLE_API_CONNECTINFO Cac;
RETURN_IF_NTSTATUS_FAILED(ConsoleInitializeConnectInfo(connectMessage, &Cac));
// BEGIN code from SetUpConsole
// Create a temporary Settings object to parse the settings into, rather
// than parsing them into the global settings object (gci).
Settings settings{};
// We need to see if we were spawned from a link. If we were, we need to
// call back into the OS shell to try to get all the console information from the link.
//
// load bearing: if you don't pass the StartupFlags, then
// GetSettingsFromLink might not even bother attempting to check the lnk.
settings.SetStartupFlags(Cac.ConsoleInfo.GetStartupFlags());
ServiceLocator::LocateSystemConfigurationProvider()->GetSettingsFromLink(&settings,
Cac.Title,
&Cac.TitleLength,
Cac.CurDir,
Cac.AppName,
&icon);
// 1. The settings we were passed contains STARTUPINFO structure settings to be applied last.
settings.ApplyStartupInfo(&Cac.ConsoleInfo);
// END code from SetUpConsole
// Take what we've collected, and bundle it up for handoff.
auto title = wil::make_bstr(Cac.Title);
auto iconPath = wil::make_bstr(icon.path.data());
TERMINAL_STARTUP_INFO myStartupInfo{
title.get(),
iconPath.get(),
icon.index
};
RETURN_IF_FAILED(handoff->EstablishPtyHandoff(inPipeTheirSide.get(),
outPipeTheirSide.get(),
signalPipeTheirSide.get(),
refHandle.get(),
serverProcess,
clientProcess.get()));
clientProcess.get(),
myStartupInfo));
TraceLoggingWrite(g_hConhostV2EventTraceProvider,
"SrvInit_DelegateToTerminalSucceeded",

View File

@ -19,6 +19,12 @@ class Settings;
namespace Microsoft::Console::Interactivity
{
struct IconInfo
{
std::wstring path;
int index = 0;
};
class ISystemConfigurationProvider
{
public:
@ -36,6 +42,7 @@ namespace Microsoft::Console::Interactivity
_Inout_updates_bytes_(*pdwTitleLength) LPWSTR pwszTitle,
_Inout_ PDWORD pdwTitleLength,
_In_ PCWSTR pwszCurrDir,
_In_ PCWSTR pwszAppName) = 0;
_In_ PCWSTR pwszAppName,
_Inout_opt_ IconInfo* iconInfo) = 0;
};
}

View File

@ -49,7 +49,8 @@ void SystemConfigurationProvider::GetSettingsFromLink(
_Inout_updates_bytes_(*pdwTitleLength) LPWSTR /*pwszTitle*/,
_Inout_ PDWORD /*pdwTitleLength*/,
_In_ PCWSTR /*pwszCurrDir*/,
_In_ PCWSTR /*pwszAppName*/)
_In_ PCWSTR /*pwszAppName*/,
_Inout_opt_ IconInfo* /*iconInfo*/)
{
// While both OneCore console renderers use TrueType fonts, there is no
// advanced font support on that platform. Namely, there is no way to pick

View File

@ -37,7 +37,8 @@ namespace Microsoft::Console::Interactivity::OneCore
_Inout_updates_bytes_(*pdwTitleLength) LPWSTR pwszTitle,
_Inout_ PDWORD pdwTitleLength,
_In_ PCWSTR pwszCurrDir,
_In_ PCWSTR pwszAppName) override;
_In_ PCWSTR pwszAppName,
_Inout_opt_ IconInfo* iconInfo) override;
private:
static constexpr UINT s_DefaultCaretBlinkTime = 530; // milliseconds

View File

@ -60,7 +60,8 @@ void SystemConfigurationProvider::GetSettingsFromLink(
_Inout_updates_bytes_(*pdwTitleLength) LPWSTR pwszTitle,
_Inout_ PDWORD pdwTitleLength,
_In_ PCWSTR pwszCurrDir,
_In_ PCWSTR pwszAppName)
_In_ PCWSTR pwszAppName,
_Inout_opt_ IconInfo* iconInfo)
{
auto& gci = ServiceLocator::LocateGlobals().getConsoleInformation();
WCHAR wszLinkTarget[MAX_PATH] = { 0 };
@ -72,8 +73,15 @@ void SystemConfigurationProvider::GetSettingsFromLink(
// Did we get started from a link?
if (pLinkSettings->GetStartupFlags() & STARTF_TITLEISLINKNAME)
{
if (SUCCEEDED(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED)))
auto initializedCom = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
// GH#9458: If it's RPC_E_CHANGED_MODE, that's okay, we're doing a
// defterm and have already started COM. We can continue on here.
if (SUCCEEDED(initializedCom) || initializedCom == RPC_E_CHANGED_MODE)
{
// Don't CoUninitialize if we still need COM for defterm.
auto unInitCom = wil::scope_exit([initializedCom]() { if (SUCCEEDED(initializedCom)){CoUninitialize();} });
const auto cch = *pdwTitleLength / sizeof(wchar_t);
gci.SetLinkTitle(std::wstring(pwszTitle, cch));
@ -156,7 +164,6 @@ void SystemConfigurationProvider::GetSettingsFromLink(
// settings based on title.
pLinkSettings->UnsetStartupFlag(STARTF_TITLEISLINKNAME);
}
CoUninitialize();
}
}
@ -191,7 +198,19 @@ void SystemConfigurationProvider::GetSettingsFromLink(
if (wszIconLocation[0] != L'\0')
{
LOG_IF_FAILED(Icon::Instance().LoadIconsFromPath(wszIconLocation, iIconIndex));
// GH#9458, GH#13111 - when this is executed during defterm startup,
// we'll pass in an iconInfo pointer, which we should fill with the
// selected icon path and index, rather than loading the icon with our
// global Icon class.
if (iconInfo)
{
iconInfo->path = std::wstring{ wszIconLocation };
iconInfo->index = iIconIndex;
}
else
{
LOG_IF_FAILED(Icon::Instance().LoadIconsFromPath(wszIconLocation, iIconIndex));
}
}
if (!IsValidCodePage(pLinkSettings->GetCodePage()))

View File

@ -37,7 +37,8 @@ namespace Microsoft::Console::Interactivity::Win32
_Inout_updates_bytes_(*pdwTitleLength) LPWSTR pwszTitle,
_Inout_ PDWORD pdwTitleLength,
_In_ PCWSTR pwszCurrDir,
_In_ PCWSTR pwszAppName);
_In_ PCWSTR pwszAppName,
_Inout_opt_ IconInfo* iconInfo);
private:
static const ULONG s_DefaultCursorWidth = 1;