mirror of
https://github.com/microsoft/terminal.git
synced 2025-12-12 18:41:01 -06:00
Add ITerminalHandoff3 in preparation for overlapped pipes (#17575)
Without a renderer in #17510 we cannot skip "frames" anymore. As such, using overlapped IO becomes crucial to avoid a regression in performance. ITerminalHandoff3 fixes this by allowing the terminal to pick the pipes it wants, which mirrors CreatePseudoConsole where the caller can also pick its own pipes. ## Validation Steps Performed * Do a handoff with the dev build * Input/Output works ✅
This commit is contained in:
parent
1ac221a7a5
commit
1f83146644
@ -111,8 +111,7 @@
|
|||||||
<com:ComInterface>
|
<com:ComInterface>
|
||||||
<com:ProxyStub Id="1D1852F4-ADAD-42B6-9A43-9437AAAD7717" DisplayName="OpenConsoleHandoffProxy" Path="OpenConsoleProxy.dll"/>
|
<com:ProxyStub Id="1D1852F4-ADAD-42B6-9A43-9437AAAD7717" DisplayName="OpenConsoleHandoffProxy" Path="OpenConsoleProxy.dll"/>
|
||||||
<com:Interface Id="E686C757-9A35-4A1C-B3CE-0BCC8B5C69F4" ProxyStubClsid="1D1852F4-ADAD-42B6-9A43-9437AAAD7717"/>
|
<com:Interface Id="E686C757-9A35-4A1C-B3CE-0BCC8B5C69F4" ProxyStubClsid="1D1852F4-ADAD-42B6-9A43-9437AAAD7717"/>
|
||||||
<com:Interface Id="59D55CCE-FC8A-48B4-ACE8-0A9286C6557F" ProxyStubClsid="1D1852F4-ADAD-42B6-9A43-9437AAAD7717"/> <!-- ITerminalHandoff -->
|
<com:Interface Id="6F23DA90-15C5-4203-9DB0-64E73F1B1B00" ProxyStubClsid="1D1852F4-ADAD-42B6-9A43-9437AAAD7717"/> <!-- ITerminalHandoff3 -->
|
||||||
<com:Interface Id="AA6B364F-4A50-4176-9002-0AE755E7B5EF" ProxyStubClsid="1D1852F4-ADAD-42B6-9A43-9437AAAD7717"/> <!-- ITerminalHandoff2 -->
|
|
||||||
<com:Interface Id="746E6BC0-AB05-4E38-AB14-71E86763141F" ProxyStubClsid="1D1852F4-ADAD-42B6-9A43-9437AAAD7717"/>
|
<com:Interface Id="746E6BC0-AB05-4E38-AB14-71E86763141F" ProxyStubClsid="1D1852F4-ADAD-42B6-9A43-9437AAAD7717"/>
|
||||||
</com:ComInterface>
|
</com:ComInterface>
|
||||||
</com:Extension>
|
</com:Extension>
|
||||||
|
|||||||
@ -111,8 +111,7 @@
|
|||||||
<com:ComInterface>
|
<com:ComInterface>
|
||||||
<com:ProxyStub Id="DEC4804D-56D1-4F73-9FBE-6828E7C85C56" DisplayName="OpenConsoleHandoffProxy" Path="OpenConsoleProxy.dll"/>
|
<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="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"/> <!-- ITerminalHandoff -->
|
<com:Interface Id="6F23DA90-15C5-4203-9DB0-64E73F1B1B00" ProxyStubClsid="DEC4804D-56D1-4F73-9FBE-6828E7C85C56"/> <!-- ITerminalHandoff3 -->
|
||||||
<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:Interface Id="746E6BC0-AB05-4E38-AB14-71E86763141F" ProxyStubClsid="DEC4804D-56D1-4F73-9FBE-6828E7C85C56"/>
|
||||||
</com:ComInterface>
|
</com:ComInterface>
|
||||||
</com:Extension>
|
</com:Extension>
|
||||||
|
|||||||
@ -200,8 +200,7 @@
|
|||||||
<com:ComInterface>
|
<com:ComInterface>
|
||||||
<com:ProxyStub Id="1833E661-CC81-4DD0-87C6-C2F74BD39EFA" DisplayName="OpenConsoleHandoffProxy" Path="OpenConsoleProxy.dll"/>
|
<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="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"/> <!-- ITerminalHandoff -->
|
<com:Interface Id="6F23DA90-15C5-4203-9DB0-64E73F1B1B00" ProxyStubClsid="1833E661-CC81-4DD0-87C6-C2F74BD39EFA"/> <!-- ITerminalHandoff3 -->
|
||||||
<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:Interface Id="746E6BC0-AB05-4E38-AB14-71E86763141F" ProxyStubClsid="1833E661-CC81-4DD0-87C6-C2F74BD39EFA"/>
|
||||||
</com:ComInterface>
|
</com:ComInterface>
|
||||||
</com:Extension>
|
</com:Extension>
|
||||||
|
|||||||
@ -200,8 +200,7 @@
|
|||||||
<com:ComInterface>
|
<com:ComInterface>
|
||||||
<com:ProxyStub Id="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F" DisplayName="OpenConsoleHandoffProxy" Path="OpenConsoleProxy.dll"/>
|
<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="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"/> <!-- ITerminalHandoff -->
|
<com:Interface Id="6F23DA90-15C5-4203-9DB0-64E73F1B1B00" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/> <!-- ITerminalHandoff3 -->
|
||||||
<com:Interface Id="AA6B364F-4A50-4176-9002-0AE755E7B5EF" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/> <!-- ITerminalHandoff2 -->
|
|
||||||
<com:Interface Id="746E6BC0-AB05-4E38-AB14-71E86763141F" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/>
|
<com:Interface Id="746E6BC0-AB05-4E38-AB14-71E86763141F" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/>
|
||||||
</com:ComInterface>
|
</com:ComInterface>
|
||||||
</com:Extension>
|
</com:Extension>
|
||||||
|
|||||||
@ -72,20 +72,6 @@ HRESULT CTerminalHandoff::s_StopListeningLocked()
|
|||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Routine Description:
|
|
||||||
// - Helper to duplicate a handle to ourselves so we can keep holding onto it
|
|
||||||
// after the caller frees the original one.
|
|
||||||
// Arguments:
|
|
||||||
// - in - Handle to duplicate
|
|
||||||
// - out - Where to place the duplicated value
|
|
||||||
// Return Value:
|
|
||||||
// - S_OK or Win32 error from `::DuplicateHandle`
|
|
||||||
static HRESULT _duplicateHandle(const HANDLE in, HANDLE& out) noexcept
|
|
||||||
{
|
|
||||||
RETURN_IF_WIN32_BOOL_FALSE(::DuplicateHandle(GetCurrentProcess(), in, GetCurrentProcess(), &out, 0, FALSE, DUPLICATE_SAME_ACCESS));
|
|
||||||
return S_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Routine Description:
|
// Routine Description:
|
||||||
// - Receives the terminal handoff via COM from the other process,
|
// - Receives the terminal handoff via COM from the other process,
|
||||||
// duplicates handles as COM will free those given on the way out,
|
// duplicates handles as COM will free those given on the way out,
|
||||||
@ -102,7 +88,7 @@ static HRESULT _duplicateHandle(const HANDLE in, HANDLE& out) noexcept
|
|||||||
// - E_NOT_VALID_STATE if a event handler is not registered before calling. `::DuplicateHandle`
|
// - 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
|
// 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.
|
// from the registered handler event function.
|
||||||
HRESULT CTerminalHandoff::EstablishPtyHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client, TERMINAL_STARTUP_INFO startupInfo)
|
HRESULT CTerminalHandoff::EstablishPtyHandoff(HANDLE* in, HANDLE* out, HANDLE signal, HANDLE reference, HANDLE server, HANDLE client, const TERMINAL_STARTUP_INFO* startupInfo)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -120,19 +106,8 @@ HRESULT CTerminalHandoff::EstablishPtyHandoff(HANDLE in, HANDLE out, HANDLE sign
|
|||||||
// Report an error if no one registered a handoff function before calling this.
|
// Report an error if no one registered a handoff function before calling this.
|
||||||
THROW_HR_IF_NULL(E_NOT_VALID_STATE, localPfnHandoff);
|
THROW_HR_IF_NULL(E_NOT_VALID_STATE, localPfnHandoff);
|
||||||
|
|
||||||
// Duplicate the handles from what we received.
|
|
||||||
// The contract with COM specifies that any HANDLEs we receive from the caller belong
|
|
||||||
// to the caller and will be freed when we leave the scope of this method.
|
|
||||||
// Making our own duplicate copy ensures they hang around in our lifetime.
|
|
||||||
THROW_IF_FAILED(_duplicateHandle(in, in));
|
|
||||||
THROW_IF_FAILED(_duplicateHandle(out, out));
|
|
||||||
THROW_IF_FAILED(_duplicateHandle(signal, signal));
|
|
||||||
THROW_IF_FAILED(_duplicateHandle(ref, ref));
|
|
||||||
THROW_IF_FAILED(_duplicateHandle(server, server));
|
|
||||||
THROW_IF_FAILED(_duplicateHandle(client, client));
|
|
||||||
|
|
||||||
// Call registered handler from when we started listening.
|
// Call registered handler from when we started listening.
|
||||||
THROW_IF_FAILED(localPfnHandoff(in, out, signal, ref, server, client, startupInfo));
|
THROW_IF_FAILED(localPfnHandoff(in, out, signal, reference, server, client, startupInfo));
|
||||||
|
|
||||||
#pragma warning(suppress : 26477)
|
#pragma warning(suppress : 26477)
|
||||||
TraceLoggingWrite(
|
TraceLoggingWrite(
|
||||||
|
|||||||
@ -28,19 +28,13 @@ Author(s):
|
|||||||
#define __CLSID_CTerminalHandoff "051F34EE-C1FD-4B19-AF75-9BA54648434C"
|
#define __CLSID_CTerminalHandoff "051F34EE-C1FD-4B19-AF75-9BA54648434C"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using NewHandoffFunction = HRESULT (*)(HANDLE, HANDLE, HANDLE, HANDLE, HANDLE, HANDLE, TERMINAL_STARTUP_INFO);
|
using NewHandoffFunction = HRESULT (*)(HANDLE* in, HANDLE* out, HANDLE signal, HANDLE reference, HANDLE server, HANDLE client, const TERMINAL_STARTUP_INFO* startupInfo);
|
||||||
|
|
||||||
struct __declspec(uuid(__CLSID_CTerminalHandoff))
|
struct __declspec(uuid(__CLSID_CTerminalHandoff))
|
||||||
CTerminalHandoff : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::RuntimeClassType::ClassicCom>, ITerminalHandoff2>
|
CTerminalHandoff : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::RuntimeClassType::ClassicCom>, ITerminalHandoff3>
|
||||||
{
|
{
|
||||||
#pragma region ITerminalHandoff
|
#pragma region ITerminalHandoff
|
||||||
STDMETHODIMP EstablishPtyHandoff(HANDLE in,
|
STDMETHODIMP EstablishPtyHandoff(HANDLE* in, HANDLE* out, HANDLE signal, HANDLE reference, HANDLE server, HANDLE client, const TERMINAL_STARTUP_INFO* startupInfo) override;
|
||||||
HANDLE out,
|
|
||||||
HANDLE signal,
|
|
||||||
HANDLE ref,
|
|
||||||
HANDLE server,
|
|
||||||
HANDLE client,
|
|
||||||
TERMINAL_STARTUP_INFO startupInfo) override;
|
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,6 @@
|
|||||||
#include "ConptyConnection.h"
|
#include "ConptyConnection.h"
|
||||||
|
|
||||||
#include <conpty-static.h>
|
#include <conpty-static.h>
|
||||||
#include <winternl.h>
|
|
||||||
|
|
||||||
#include "CTerminalHandoff.h"
|
#include "CTerminalHandoff.h"
|
||||||
#include "LibraryResources.h"
|
#include "LibraryResources.h"
|
||||||
@ -173,33 +172,10 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||||||
}
|
}
|
||||||
CATCH_RETURN();
|
CATCH_RETURN();
|
||||||
|
|
||||||
ConptyConnection::ConptyConnection(const HANDLE hSig,
|
// Who decided that?
|
||||||
const HANDLE hIn,
|
#pragma warning(suppress : 26455) // Default constructor should not throw. Declare it 'noexcept' (f.6).
|
||||||
const HANDLE hOut,
|
ConptyConnection::ConptyConnection()
|
||||||
const HANDLE hRef,
|
|
||||||
const HANDLE hServerProcess,
|
|
||||||
const HANDLE hClientProcess,
|
|
||||||
const TERMINAL_STARTUP_INFO& startupInfo) :
|
|
||||||
_rows{ 25 },
|
|
||||||
_cols{ 80 },
|
|
||||||
_inPipe{ hIn },
|
|
||||||
_outPipe{ hOut }
|
|
||||||
{
|
{
|
||||||
_sessionId = Utils::CreateGuid();
|
|
||||||
|
|
||||||
THROW_IF_FAILED(ConptyPackPseudoConsole(hServerProcess, hRef, hSig, &_hPC));
|
|
||||||
_piClient.hProcess = hClientProcess;
|
|
||||||
|
|
||||||
_startupInfo.title = winrt::hstring{ startupInfo.pszTitle, SysStringLen(startupInfo.pszTitle) };
|
|
||||||
_startupInfo.iconPath = winrt::hstring{ startupInfo.pszIconPath, SysStringLen(startupInfo.pszIconPath) };
|
|
||||||
_startupInfo.iconIndex = startupInfo.iconIndex;
|
|
||||||
_startupInfo.showWindow = startupInfo.wShowWindow;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_commandline = _commandlineFromProcess(hClientProcess);
|
|
||||||
}
|
|
||||||
CATCH_LOG()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function Description:
|
// Function Description:
|
||||||
@ -319,6 +295,53 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static wil::unique_hfile duplicateHandle(const HANDLE in)
|
||||||
|
{
|
||||||
|
wil::unique_hfile h;
|
||||||
|
THROW_IF_WIN32_BOOL_FALSE(DuplicateHandle(GetCurrentProcess(), in, GetCurrentProcess(), h.addressof(), 0, FALSE, DUPLICATE_SAME_ACCESS));
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Misdiagnosis: out is being tested right in the first line.
|
||||||
|
#pragma warning(suppress : 26430) // Symbol 'out' is not tested for nullness on all paths (f.23).
|
||||||
|
void ConptyConnection::InitializeFromHandoff(HANDLE* in, HANDLE* out, HANDLE signal, HANDLE reference, HANDLE server, HANDLE client, const TERMINAL_STARTUP_INFO* startupInfo)
|
||||||
|
{
|
||||||
|
THROW_HR_IF(E_UNEXPECTED, !in || !out || !startupInfo);
|
||||||
|
|
||||||
|
_sessionId = Utils::CreateGuid();
|
||||||
|
|
||||||
|
wil::unique_hfile inPipePseudoConsoleSide;
|
||||||
|
wil::unique_hfile outPipePseudoConsoleSide;
|
||||||
|
THROW_IF_WIN32_BOOL_FALSE(CreatePipe(&inPipePseudoConsoleSide, &_inPipe, nullptr, 0));
|
||||||
|
THROW_IF_WIN32_BOOL_FALSE(CreatePipe(&_outPipe, &outPipePseudoConsoleSide, nullptr, 0));
|
||||||
|
|
||||||
|
auto ownedSignal = duplicateHandle(signal);
|
||||||
|
auto ownedReference = duplicateHandle(reference);
|
||||||
|
auto ownedServer = duplicateHandle(server);
|
||||||
|
auto ownedClient = duplicateHandle(client);
|
||||||
|
|
||||||
|
THROW_IF_FAILED(ConptyPackPseudoConsole(ownedServer.get(), ownedReference.get(), ownedSignal.get(), &_hPC));
|
||||||
|
ownedServer.release();
|
||||||
|
ownedReference.release();
|
||||||
|
ownedSignal.release();
|
||||||
|
|
||||||
|
_piClient.hProcess = ownedClient.release();
|
||||||
|
|
||||||
|
_startupInfo.title = winrt::hstring{ startupInfo->pszTitle, SysStringLen(startupInfo->pszTitle) };
|
||||||
|
_startupInfo.iconPath = winrt::hstring{ startupInfo->pszIconPath, SysStringLen(startupInfo->pszIconPath) };
|
||||||
|
_startupInfo.iconIndex = startupInfo->iconIndex;
|
||||||
|
_startupInfo.showWindow = startupInfo->wShowWindow;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_commandline = _commandlineFromProcess(_piClient.hProcess);
|
||||||
|
}
|
||||||
|
CATCH_LOG()
|
||||||
|
|
||||||
|
*in = inPipePseudoConsoleSide.release();
|
||||||
|
*out = outPipePseudoConsoleSide.release();
|
||||||
|
}
|
||||||
|
|
||||||
winrt::hstring ConptyConnection::Commandline() const
|
winrt::hstring ConptyConnection::Commandline() const
|
||||||
{
|
{
|
||||||
return _commandline;
|
return _commandline;
|
||||||
@ -618,12 +641,20 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||||||
// won't wait for us, and the known exit points _do_.
|
// won't wait for us, and the known exit points _do_.
|
||||||
auto strongThis{ get_strong() };
|
auto strongThis{ get_strong() };
|
||||||
|
|
||||||
|
const auto cleanup = wil::scope_exit([this]() noexcept {
|
||||||
|
_LastConPtyClientDisconnected();
|
||||||
|
});
|
||||||
|
|
||||||
|
char buffer[128 * 1024];
|
||||||
|
DWORD read = 0;
|
||||||
|
|
||||||
|
til::u8state u8State;
|
||||||
|
std::wstring wstr;
|
||||||
|
|
||||||
// process the data of the output pipe in a loop
|
// process the data of the output pipe in a loop
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
DWORD read{};
|
const auto readFail{ !ReadFile(_outPipe.get(), &buffer[0], sizeof(buffer), &read, nullptr) };
|
||||||
|
|
||||||
const auto readFail{ !ReadFile(_outPipe.get(), _buffer.data(), gsl::narrow_cast<DWORD>(_buffer.size()), &read, nullptr) };
|
|
||||||
|
|
||||||
// When we call CancelSynchronousIo() in Close() this is the branch that's taken and gets us out of here.
|
// When we call CancelSynchronousIo() in Close() this is the branch that's taken and gets us out of here.
|
||||||
if (_isStateAtOrBeyond(ConnectionState::Closing))
|
if (_isStateAtOrBeyond(ConnectionState::Closing))
|
||||||
@ -648,7 +679,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto result{ til::u8u16(std::string_view{ _buffer.data(), read }, _u16Str, _u8State) };
|
const auto result{ til::u8u16(std::string_view{ &buffer[0], read }, wstr, u8State) };
|
||||||
if (FAILED(result))
|
if (FAILED(result))
|
||||||
{
|
{
|
||||||
// EXIT POINT
|
// EXIT POINT
|
||||||
@ -657,7 +688,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||||||
return gsl::narrow_cast<DWORD>(result);
|
return gsl::narrow_cast<DWORD>(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_u16Str.empty())
|
if (wstr.empty())
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -679,7 +710,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Pass the output to our registered event handlers
|
// Pass the output to our registered event handlers
|
||||||
TerminalOutput.raise(_u16Str);
|
TerminalOutput.raise(wstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -695,11 +726,12 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||||||
::ConptyClosePseudoConsoleTimeout(hPC, 0);
|
::ConptyClosePseudoConsoleTimeout(hPC, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT ConptyConnection::NewHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client, TERMINAL_STARTUP_INFO startupInfo) noexcept
|
HRESULT ConptyConnection::NewHandoff(HANDLE* in, HANDLE* out, HANDLE signal, HANDLE reference, HANDLE server, HANDLE client, const TERMINAL_STARTUP_INFO* startupInfo) noexcept
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_newConnectionHandlers(winrt::make<ConptyConnection>(signal, in, out, ref, server, client, startupInfo));
|
auto conn = winrt::make_self<ConptyConnection>();
|
||||||
|
conn->InitializeFromHandoff(in, out, signal, reference, server, client, startupInfo);
|
||||||
|
_newConnectionHandlers(*std::move(conn));
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
CATCH_RETURN()
|
CATCH_RETURN()
|
||||||
|
|||||||
@ -13,16 +13,9 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||||||
{
|
{
|
||||||
struct ConptyConnection : ConptyConnectionT<ConptyConnection>, BaseTerminalConnection<ConptyConnection>
|
struct ConptyConnection : ConptyConnectionT<ConptyConnection>, BaseTerminalConnection<ConptyConnection>
|
||||||
{
|
{
|
||||||
ConptyConnection(const HANDLE hSig,
|
explicit ConptyConnection();
|
||||||
const HANDLE hIn,
|
|
||||||
const HANDLE hOut,
|
|
||||||
const HANDLE hRef,
|
|
||||||
const HANDLE hServerProcess,
|
|
||||||
const HANDLE hClientProcess,
|
|
||||||
const TERMINAL_STARTUP_INFO& startupInfo);
|
|
||||||
|
|
||||||
ConptyConnection() noexcept = default;
|
|
||||||
void Initialize(const Windows::Foundation::Collections::ValueSet& settings);
|
void Initialize(const Windows::Foundation::Collections::ValueSet& settings);
|
||||||
|
void InitializeFromHandoff(HANDLE* in, HANDLE* out, HANDLE signal, HANDLE reference, HANDLE server, HANDLE client, const TERMINAL_STARTUP_INFO* startupInfo);
|
||||||
|
|
||||||
static winrt::fire_and_forget final_release(std::unique_ptr<ConptyConnection> connection);
|
static winrt::fire_and_forget final_release(std::unique_ptr<ConptyConnection> connection);
|
||||||
|
|
||||||
@ -61,15 +54,15 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static void closePseudoConsoleAsync(HPCON hPC) noexcept;
|
static void closePseudoConsoleAsync(HPCON hPC) noexcept;
|
||||||
static HRESULT NewHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client, TERMINAL_STARTUP_INFO startupInfo) noexcept;
|
static HRESULT NewHandoff(HANDLE* in, HANDLE* out, HANDLE signal, HANDLE reference, HANDLE server, HANDLE client, const TERMINAL_STARTUP_INFO* startupInfo) noexcept;
|
||||||
static winrt::hstring _commandlineFromProcess(HANDLE process);
|
static winrt::hstring _commandlineFromProcess(HANDLE process);
|
||||||
|
|
||||||
HRESULT _LaunchAttachedClient() noexcept;
|
HRESULT _LaunchAttachedClient() noexcept;
|
||||||
void _indicateExitWithStatus(unsigned int status) noexcept;
|
void _indicateExitWithStatus(unsigned int status) noexcept;
|
||||||
void _LastConPtyClientDisconnected() noexcept;
|
void _LastConPtyClientDisconnected() noexcept;
|
||||||
|
|
||||||
til::CoordType _rows{};
|
til::CoordType _rows = 120;
|
||||||
til::CoordType _cols{};
|
til::CoordType _cols = 30;
|
||||||
uint64_t _initialParentHwnd{ 0 };
|
uint64_t _initialParentHwnd{ 0 };
|
||||||
hstring _commandline{};
|
hstring _commandline{};
|
||||||
hstring _startingDirectory{};
|
hstring _startingDirectory{};
|
||||||
@ -87,9 +80,6 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
|
|||||||
wil::unique_process_information _piClient;
|
wil::unique_process_information _piClient;
|
||||||
wil::unique_any<HPCON, decltype(closePseudoConsoleAsync), closePseudoConsoleAsync> _hPC;
|
wil::unique_any<HPCON, decltype(closePseudoConsoleAsync), closePseudoConsoleAsync> _hPC;
|
||||||
|
|
||||||
til::u8state _u8State{};
|
|
||||||
std::wstring _u16Str{};
|
|
||||||
std::array<char, 4096> _buffer{};
|
|
||||||
DWORD _flags{ 0 };
|
DWORD _flags{ 0 };
|
||||||
|
|
||||||
til::env _initialEnv{};
|
til::env _initialEnv{};
|
||||||
|
|||||||
@ -2586,7 +2586,6 @@ namespace RemotingUnitTests
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
const auto result = m1->ProposeCommandline(args);
|
const auto result = m1->ProposeCommandline(args);
|
||||||
VERIFY_IS_FALSE(true, L"This should have thrown");
|
|
||||||
}
|
}
|
||||||
catch (const winrt::hresult_error& e)
|
catch (const winrt::hresult_error& e)
|
||||||
{
|
{
|
||||||
@ -2596,9 +2595,10 @@ namespace RemotingUnitTests
|
|||||||
|
|
||||||
// This is the same check in WindowManager::_proposeToMonarch.
|
// This is the same check in WindowManager::_proposeToMonarch.
|
||||||
VERIFY_IS_TRUE(e.code() == RPC_SERVER_UNAVAILABLE_HR || e.code() == RPC_CALL_FAILED_HR);
|
VERIFY_IS_TRUE(e.code() == RPC_SERVER_UNAVAILABLE_HR || e.code() == RPC_CALL_FAILED_HR);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
// just don't catch other types of exceptions. They'll take out
|
|
||||||
// TAEF, which will count as a failure.
|
VERIFY_FAIL(L"This should have thrown");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
// Copyright (c) Microsoft Corporation.
|
// Copyright (c) Microsoft Corporation.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
import "oaidl.idl";
|
import "unknwn.idl";
|
||||||
import "ocidl.idl";
|
|
||||||
|
|
||||||
typedef struct _CONSOLE_PORTABLE_ATTACH_MSG
|
typedef struct _CONSOLE_PORTABLE_ATTACH_MSG
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
// Copyright (c) Microsoft Corporation.
|
// Copyright (c) Microsoft Corporation.
|
||||||
// Licensed under the MIT license.
|
// Licensed under the MIT license.
|
||||||
|
|
||||||
import "oaidl.idl";
|
import "unknwn.idl";
|
||||||
import "ocidl.idl";
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct _TERMINAL_STARTUP_INFO
|
typedef struct _TERMINAL_STARTUP_INFO
|
||||||
{
|
{
|
||||||
@ -33,6 +31,7 @@ typedef struct _TERMINAL_STARTUP_INFO
|
|||||||
// versions of interfaces in the file here, even if the old version is no longer
|
// versions of interfaces in the file here, even if the old version is no longer
|
||||||
// in use.
|
// in use.
|
||||||
|
|
||||||
|
// This was the original prototype. The reasons for changes to it are explained below.
|
||||||
[
|
[
|
||||||
object,
|
object,
|
||||||
uuid(59D55CCE-FC8A-48B4-ACE8-0A9286C6557F)
|
uuid(59D55CCE-FC8A-48B4-ACE8-0A9286C6557F)
|
||||||
@ -47,6 +46,9 @@ typedef struct _TERMINAL_STARTUP_INFO
|
|||||||
[in, system_handle(sh_process)] HANDLE client);
|
[in, system_handle(sh_process)] HANDLE client);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// We didn't consider the need for TERMINAL_STARTUP_INFO, because Windows Terminal never had support for launching
|
||||||
|
// .lnk files in the first place. They aren't executables after all, but rather a shell thing.
|
||||||
|
// Its need quickly became apparent right after releasing ITerminalHandoff, which is why it was very short-lived.
|
||||||
[
|
[
|
||||||
object,
|
object,
|
||||||
uuid(AA6B364F-4A50-4176-9002-0AE755E7B5EF)
|
uuid(AA6B364F-4A50-4176-9002-0AE755E7B5EF)
|
||||||
@ -60,3 +62,21 @@ typedef struct _TERMINAL_STARTUP_INFO
|
|||||||
[in, system_handle(sh_process)] HANDLE client,
|
[in, system_handle(sh_process)] HANDLE client,
|
||||||
[in] TERMINAL_STARTUP_INFO startupInfo);
|
[in] TERMINAL_STARTUP_INFO startupInfo);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Quite a while later, we realized that passing the in/out handles as [in] instead of [out] has always been flawed.
|
||||||
|
// It prevents the terminal from making choices over the pipe buffer size and whether to use overlapped IO or not.
|
||||||
|
// The other handles remain [in] parameters because they have always been created internally by ConPTY.
|
||||||
|
// Additionally, passing TERMINAL_STARTUP_INFO by-value was unusual under COM as structs are usually given by-ref.
|
||||||
|
[
|
||||||
|
object,
|
||||||
|
uuid(6F23DA90-15C5-4203-9DB0-64E73F1B1B00)
|
||||||
|
] interface ITerminalHandoff3 : IUnknown
|
||||||
|
{
|
||||||
|
HRESULT EstablishPtyHandoff([out, system_handle(sh_pipe)] HANDLE* in,
|
||||||
|
[out, system_handle(sh_pipe)] HANDLE* out,
|
||||||
|
[in, system_handle(sh_pipe)] HANDLE signal,
|
||||||
|
[in, system_handle(sh_file)] HANDLE reference,
|
||||||
|
[in, system_handle(sh_process)] HANDLE server,
|
||||||
|
[in, system_handle(sh_process)] HANDLE client,
|
||||||
|
[in] const TERMINAL_STARTUP_INFO* startupInfo);
|
||||||
|
};
|
||||||
|
|||||||
@ -457,19 +457,8 @@ try
|
|||||||
|
|
||||||
wil::unique_handle signalPipeTheirSide;
|
wil::unique_handle signalPipeTheirSide;
|
||||||
wil::unique_handle signalPipeOurSide;
|
wil::unique_handle signalPipeOurSide;
|
||||||
|
|
||||||
wil::unique_handle inPipeTheirSide;
|
|
||||||
wil::unique_handle inPipeOurSide;
|
|
||||||
|
|
||||||
wil::unique_handle outPipeTheirSide;
|
|
||||||
wil::unique_handle outPipeOurSide;
|
|
||||||
|
|
||||||
RETURN_IF_WIN32_BOOL_FALSE(CreatePipe(signalPipeOurSide.addressof(), signalPipeTheirSide.addressof(), nullptr, 0));
|
RETURN_IF_WIN32_BOOL_FALSE(CreatePipe(signalPipeOurSide.addressof(), signalPipeTheirSide.addressof(), nullptr, 0));
|
||||||
|
|
||||||
RETURN_IF_WIN32_BOOL_FALSE(CreatePipe(inPipeOurSide.addressof(), inPipeTheirSide.addressof(), nullptr, 0));
|
|
||||||
|
|
||||||
RETURN_IF_WIN32_BOOL_FALSE(CreatePipe(outPipeTheirSide.addressof(), outPipeOurSide.addressof(), nullptr, 0));
|
|
||||||
|
|
||||||
TraceLoggingWrite(g_hConhostV2EventTraceProvider,
|
TraceLoggingWrite(g_hConhostV2EventTraceProvider,
|
||||||
"SrvInit_ReceiveHandoff_OpenedPipes",
|
"SrvInit_ReceiveHandoff_OpenedPipes",
|
||||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||||
@ -491,7 +480,7 @@ try
|
|||||||
|
|
||||||
const auto serverProcess = GetCurrentProcess();
|
const auto serverProcess = GetCurrentProcess();
|
||||||
|
|
||||||
::Microsoft::WRL::ComPtr<ITerminalHandoff2> handoff;
|
::Microsoft::WRL::ComPtr<ITerminalHandoff3> handoff;
|
||||||
|
|
||||||
TraceLoggingWrite(g_hConhostV2EventTraceProvider,
|
TraceLoggingWrite(g_hConhostV2EventTraceProvider,
|
||||||
"SrvInit_PrepareToCreateDelegationTerminal",
|
"SrvInit_PrepareToCreateDelegationTerminal",
|
||||||
@ -566,21 +555,21 @@ try
|
|||||||
|
|
||||||
myStartupInfo.wShowWindow = settings.GetShowWindow();
|
myStartupInfo.wShowWindow = settings.GetShowWindow();
|
||||||
|
|
||||||
RETURN_IF_FAILED(handoff->EstablishPtyHandoff(inPipeTheirSide.get(),
|
wil::unique_handle inPipeOurSide;
|
||||||
outPipeTheirSide.get(),
|
wil::unique_handle outPipeOurSide;
|
||||||
|
RETURN_IF_FAILED(handoff->EstablishPtyHandoff(inPipeOurSide.addressof(),
|
||||||
|
outPipeOurSide.addressof(),
|
||||||
signalPipeTheirSide.get(),
|
signalPipeTheirSide.get(),
|
||||||
refHandle.get(),
|
refHandle.get(),
|
||||||
serverProcess,
|
serverProcess,
|
||||||
clientProcess.get(),
|
clientProcess.get(),
|
||||||
myStartupInfo));
|
&myStartupInfo));
|
||||||
|
|
||||||
TraceLoggingWrite(g_hConhostV2EventTraceProvider,
|
TraceLoggingWrite(g_hConhostV2EventTraceProvider,
|
||||||
"SrvInit_DelegateToTerminalSucceeded",
|
"SrvInit_DelegateToTerminalSucceeded",
|
||||||
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE),
|
||||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
TraceLoggingKeyword(TIL_KEYWORD_TRACE));
|
||||||
|
|
||||||
inPipeTheirSide.reset();
|
|
||||||
outPipeTheirSide.reset();
|
|
||||||
signalPipeTheirSide.reset();
|
signalPipeTheirSide.reset();
|
||||||
|
|
||||||
// GH#13211 - Make sure the terminal obeys the resizing quirk. Otherwise,
|
// GH#13211 - Make sure the terminal obeys the resizing quirk. Otherwise,
|
||||||
|
|||||||
@ -26,7 +26,7 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
|
|||||||
// state structure for maintenance of UTF-8 partials
|
// state structure for maintenance of UTF-8 partials
|
||||||
struct u8state
|
struct u8state
|
||||||
{
|
{
|
||||||
char partials[4];
|
char partials[4]{};
|
||||||
uint8_t have{};
|
uint8_t have{};
|
||||||
uint8_t want{};
|
uint8_t want{};
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user