Skip to content

Commit

Permalink
Add server process and client reference handle to ITerminalHandoff so…
Browse files Browse the repository at this point in the history
… we could make a true HPCON on the receiving side. Reguid interface for ITerminalHandoff. Make HPCON packer and pack it on inbound connection.
  • Loading branch information
miniksa committed May 21, 2021
1 parent 87ac76f commit 812a97f
Show file tree
Hide file tree
Showing 11 changed files with 70 additions and 14 deletions.
2 changes: 1 addition & 1 deletion src/cascadia/CascadiaPackage/Package-Dev.appxmanifest
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@
<com:ComInterface>
<com:ProxyStub Id="DEC4804D-56D1-4F73-9FBE-6828E7C85C56" DisplayName="OpenConsoleHandoffProxy" Path="OpenConsoleProxy.dll"/>
<com:Interface Id="2B607BC1-43EB-40C3-95AE-2856ADDB7F23" ProxyStubClsid="DEC4804D-56D1-4F73-9FBE-6828E7C85C56"/>
<com:Interface Id="FA1E3AB4-9AEC-4A3C-96CA-E6078C30BD74" ProxyStubClsid="DEC4804D-56D1-4F73-9FBE-6828E7C85C56"/>
<com:Interface Id="59D55CCE-FC8A-48B4-ACE8-0A9286C6557F" ProxyStubClsid="DEC4804D-56D1-4F73-9FBE-6828E7C85C56"/>
</com:ComInterface>
</com:Extension>
<com:Extension Category="windows.comServer">
Expand Down
2 changes: 1 addition & 1 deletion src/cascadia/CascadiaPackage/Package-Pre.appxmanifest
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@
<com:ComInterface>
<com:ProxyStub Id="1833E661-CC81-4DD0-87C6-C2F74BD39EFA" DisplayName="OpenConsoleHandoffProxy" Path="OpenConsoleProxy.dll"/>
<com:Interface Id="2B607BC1-43EB-40C3-95AE-2856ADDB7F23" ProxyStubClsid="1833E661-CC81-4DD0-87C6-C2F74BD39EFA"/>
<com:Interface Id="FA1E3AB4-9AEC-4A3C-96CA-E6078C30BD74" ProxyStubClsid="1833E661-CC81-4DD0-87C6-C2F74BD39EFA"/>
<com:Interface Id="59D55CCE-FC8A-48B4-ACE8-0A9286C6557F" ProxyStubClsid="1833E661-CC81-4DD0-87C6-C2F74BD39EFA"/>
</com:ComInterface>
</com:Extension>
<com:Extension Category="windows.comServer">
Expand Down
2 changes: 1 addition & 1 deletion src/cascadia/CascadiaPackage/Package.appxmanifest
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@
<com:ComInterface>
<com:ProxyStub Id="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F" DisplayName="OpenConsoleHandoffProxy" Path="OpenConsoleProxy.dll"/>
<com:Interface Id="2B607BC1-43EB-40C3-95AE-2856ADDB7F23" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/>
<com:Interface Id="FA1E3AB4-9AEC-4A3C-96CA-E6078C30BD74" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/>
<com:Interface Id="59D55CCE-FC8A-48B4-ACE8-0A9286C6557F" ProxyStubClsid="3171DE52-6EFA-4AEF-8A9F-D02BD67E7A4F"/>
</com:ComInterface>
</com:Extension> -->
<com:Extension Category="windows.comServer">
Expand Down
12 changes: 8 additions & 4 deletions src/cascadia/TerminalConnection/CTerminalHandoff.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,14 @@ static HRESULT _duplicateHandle(const HANDLE in, HANDLE& out) noexcept
// - in - PTY input handle that we will read from
// - out - PTY output handle that we will write to
// - signal - PTY signal handle for out of band messaging
// - process - Process handle to client so we can track its lifetime and exit appropriately
// - ref - Client reference handle for console session so it stays alive until we let go
// - server - PTY process handle to track for lifetime/cleanup
// - client - Process handle to client so we can track its lifetime and exit appropriately
// Return Value:
// - 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 process) noexcept
HRESULT CTerminalHandoff::EstablishPtyHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client) noexcept
{
// Report an error if no one registered a handoff function before calling this.
RETURN_HR_IF_NULL(E_NOT_VALID_STATE, _pfnHandoff);
Expand All @@ -101,8 +103,10 @@ HRESULT CTerminalHandoff::EstablishPtyHandoff(HANDLE in, HANDLE out, HANDLE sign
RETURN_IF_FAILED(_duplicateHandle(in, in));
RETURN_IF_FAILED(_duplicateHandle(out, out));
RETURN_IF_FAILED(_duplicateHandle(signal, signal));
RETURN_IF_FAILED(_duplicateHandle(process, process));
RETURN_IF_FAILED(_duplicateHandle(ref, ref));
RETURN_IF_FAILED(_duplicateHandle(server, server));
RETURN_IF_FAILED(_duplicateHandle(client, client));

// Call registered handler from when we started listening.
return _pfnHandoff(in, out, signal, process);
return _pfnHandoff(in, out, signal, ref, server, client);
}
6 changes: 4 additions & 2 deletions src/cascadia/TerminalConnection/CTerminalHandoff.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Author(s):
#define __CLSID_CTerminalHandoff "051F34EE-C1FD-4B19-AF75-9BA54648434C"
#endif

using NewHandoffFunction = HRESULT (*)(HANDLE, HANDLE, HANDLE, HANDLE);
using NewHandoffFunction = HRESULT (*)(HANDLE, HANDLE, HANDLE, HANDLE, HANDLE, HANDLE);

struct __declspec(uuid(__CLSID_CTerminalHandoff))
CTerminalHandoff : public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::RuntimeClassType::ClassicCom>, ITerminalHandoff>
Expand All @@ -35,7 +35,9 @@ struct __declspec(uuid(__CLSID_CTerminalHandoff))
STDMETHODIMP EstablishPtyHandoff(HANDLE in,
HANDLE out,
HANDLE signal,
HANDLE process) noexcept override;
HANDLE ref,
HANDLE server,
HANDLE client) noexcept override;

#pragma endregion

Expand Down
8 changes: 5 additions & 3 deletions src/cascadia/TerminalConnection/ConptyConnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,8 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
ConptyConnection::ConptyConnection(const HANDLE hSig,
const HANDLE hIn,
const HANDLE hOut,
const HANDLE hRef,
const HANDLE hServerProcess,
const HANDLE hClientProcess) :
_initialRows{ 25 },
_initialCols{ 80 },
Expand All @@ -208,7 +210,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
_inPipe{ hIn },
_outPipe{ hOut }
{
hSig; // TODO: GH 9464 this needs to be packed into the hpcon
THROW_IF_FAILED(ConptyPackPsuedoConsole(hServerProcess, hRef, hSig, &_hPC));
if (_guid == guid{})
{
_guid = Utils::CreateGuid();
Expand Down Expand Up @@ -500,10 +502,10 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
winrt::event_token ConptyConnection::NewConnection(NewConnectionHandler const& handler) { return _newConnectionHandlers.add(handler); };
void ConptyConnection::NewConnection(winrt::event_token const& token) { _newConnectionHandlers.remove(token); };

HRESULT ConptyConnection::NewHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE process) noexcept
HRESULT ConptyConnection::NewHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client) noexcept
try
{
auto conn = winrt::make<implementation::ConptyConnection>(signal, in, out, process);
auto conn = winrt::make<implementation::ConptyConnection>(signal, in, out, ref, server, client);
_newConnectionHandlers(conn);

return S_OK;
Expand Down
4 changes: 3 additions & 1 deletion src/cascadia/TerminalConnection/ConptyConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
ConptyConnection(const HANDLE hSig,
const HANDLE hIn,
const HANDLE hOut,
const HANDLE hRef,
const HANDLE hServerProcess,
const HANDLE hClientProcess);

ConptyConnection(
Expand Down Expand Up @@ -54,7 +56,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
void _indicateExitWithStatus(unsigned int status) noexcept;
void _ClientTerminated() noexcept;

static HRESULT NewHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE process) noexcept;
static HRESULT NewHandoff(HANDLE in, HANDLE out, HANDLE signal, HANDLE ref, HANDLE server, HANDLE client) noexcept;

uint32_t _initialRows{};
uint32_t _initialCols{};
Expand Down
4 changes: 3 additions & 1 deletion src/host/proxy/ITerminalHandoff.idl
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import "ocidl.idl";

[
object,
uuid(FA1E3AB4-9AEC-4A3C-96CA-E6078C30BD74)
uuid(59D55CCE-FC8A-48B4-ACE8-0A9286C6557F)
] interface ITerminalHandoff : 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);
};
11 changes: 11 additions & 0 deletions src/host/srvinit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "../types/inc/GlyphWidth.hpp"

#include "../server/DeviceHandle.h"
#include "../server/Entrypoints.h"
#include "../server/IoSorter.h"

Expand Down Expand Up @@ -414,13 +415,23 @@ try
wil::unique_handle clientProcess{ OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, TRUE, static_cast<DWORD>(connectMessage->Descriptor.Process)) };
RETURN_LAST_ERROR_IF_NULL(clientProcess.get());

wil::unique_handle refHandle;
RETURN_IF_NTSTATUS_FAILED(DeviceHandle::CreateClientHandle(refHandle.addressof(),
Server,
L"\\Reference",
FALSE));

const auto serverProcess = GetCurrentProcess();

::Microsoft::WRL::ComPtr<ITerminalHandoff> handoff;

RETURN_IF_FAILED(CoCreateInstance(g.handoffTerminalClsid.value(), nullptr, CLSCTX_LOCAL_SERVER, IID_PPV_ARGS(&handoff)));

RETURN_IF_FAILED(handoff->EstablishPtyHandoff(inPipeTheirSide.get(),
outPipeTheirSide.get(),
signalPipeTheirSide.get(),
refHandle.get(),
serverProcess,
clientProcess.get()));

inPipeTheirSide.release();
Expand Down
2 changes: 2 additions & 0 deletions src/inc/conpty-static.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ HRESULT WINAPI ConptyResizePseudoConsole(HPCON hPC, COORD size);

VOID WINAPI ConptyClosePseudoConsole(HPCON hPC);

HRESULT WINAPI ConptyPackPsuedoConsole(HANDLE hServerProcess, HANDLE hRef, HANDLE hSignal, HPCON* phPC);

#ifdef __cplusplus
}
#endif
31 changes: 31 additions & 0 deletions src/winconpty/winconpty.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -400,4 +400,35 @@ extern "C" VOID WINAPI ConptyClosePseudoConsole(_In_ HPCON hPC)
}
}

// NOTE: This one is not defined in the Windows headers but is
// necessary for our outside recipient in the Terminal
// to set up a PTY session in fundamentally the same way as the
// Creation functions. Using the same HPCON pack enables
// resizing and closing to "just work."

// Function Description:
// Packs loose handle information for an inbound ConPTY
// session into the same HPCON as a created session.
extern "C" HRESULT WINAPI ConptyPackPsuedoConsole(_In_ HANDLE hProcess,
_In_ HANDLE hRef,
_In_ HANDLE hSignal,
_Out_ HPCON* phPC)
{
RETURN_HR_IF(E_INVALIDARG, nullptr == phPC);
*phPC = nullptr;
RETURN_HR_IF(E_INVALIDARG, !_HandleIsValid(hProcess));
RETURN_HR_IF(E_INVALIDARG, !_HandleIsValid(hRef));
RETURN_HR_IF(E_INVALIDARG, !_HandleIsValid(hSignal));

PseudoConsole* pPty = (PseudoConsole*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PseudoConsole));
RETURN_IF_NULL_ALLOC(pPty);

RETURN_IF_WIN32_BOOL_FALSE(DuplicateHandle(GetCurrentProcess(), hProcess, GetCurrentProcess(), &pPty->hConPtyProcess, 0, FALSE, DUPLICATE_SAME_ACCESS));
RETURN_IF_WIN32_BOOL_FALSE(DuplicateHandle(GetCurrentProcess(), hRef, GetCurrentProcess(), &pPty->hPtyReference, 0, FALSE, DUPLICATE_SAME_ACCESS));
RETURN_IF_WIN32_BOOL_FALSE(DuplicateHandle(GetCurrentProcess(), hSignal, GetCurrentProcess(), &pPty->hSignal, 0, FALSE, DUPLICATE_SAME_ACCESS));

*phPC = (HPCON)pPty;
return S_OK;
}

#pragma warning(pop)

0 comments on commit 812a97f

Please sign in to comment.