-
Notifications
You must be signed in to change notification settings - Fork 8.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ITerminalHandoff3 in preparation for overlapped pipes #17575
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -72,20 +72,6 @@ HRESULT CTerminalHandoff::s_StopListeningLocked() | |
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: | ||
// - Receives the terminal handoff via COM from the other process, | ||
// 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` | ||
// 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, 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 | ||
{ | ||
|
@@ -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. | ||
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)); | ||
Comment on lines
-123
to
-132
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📝 got moved to |
||
|
||
// 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) | ||
TraceLoggingWrite( | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,6 @@ | |
#include "ConptyConnection.h" | ||
|
||
#include <conpty-static.h> | ||
#include <winternl.h> | ||
|
||
#include "CTerminalHandoff.h" | ||
#include "LibraryResources.h" | ||
|
@@ -173,33 +172,10 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation | |
} | ||
CATCH_RETURN(); | ||
|
||
ConptyConnection::ConptyConnection(const HANDLE hSig, | ||
const HANDLE hIn, | ||
const HANDLE hOut, | ||
const HANDLE hRef, | ||
const HANDLE hServerProcess, | ||
const HANDLE hClientProcess, | ||
const TERMINAL_STARTUP_INFO& startupInfo) : | ||
_rows{ 25 }, | ||
_cols{ 80 }, | ||
_inPipe{ hIn }, | ||
_outPipe{ hOut } | ||
// Who decided that? | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hah |
||
#pragma warning(suppress : 26455) // Default constructor should not throw. Declare it 'noexcept' (f.6). | ||
ConptyConnection::ConptyConnection() | ||
{ | ||
_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: | ||
|
@@ -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 | ||
{ | ||
return _commandline; | ||
|
@@ -618,12 +641,20 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation | |
// won't wait for us, and the known exit points _do_. | ||
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 | ||
while (true) | ||
{ | ||
DWORD read{}; | ||
|
||
const auto readFail{ !ReadFile(_outPipe.get(), _buffer.data(), gsl::narrow_cast<DWORD>(_buffer.size()), &read, nullptr) }; | ||
const auto readFail{ !ReadFile(_outPipe.get(), &buffer[0], sizeof(buffer), &read, nullptr) }; | ||
|
||
// When we call CancelSynchronousIo() in Close() this is the branch that's taken and gets us out of here. | ||
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)) | ||
{ | ||
// EXIT POINT | ||
|
@@ -657,7 +688,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation | |
return gsl::narrow_cast<DWORD>(result); | ||
} | ||
|
||
if (_u16Str.empty()) | ||
if (wstr.empty()) | ||
{ | ||
return 0; | ||
} | ||
|
@@ -679,7 +710,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation | |
} | ||
|
||
// Pass the output to our registered event handlers | ||
TerminalOutput.raise(_u16Str); | ||
TerminalOutput.raise(wstr); | ||
} | ||
|
||
return 0; | ||
|
@@ -695,11 +726,12 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation | |
::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 | ||
{ | ||
_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; | ||
} | ||
CATCH_RETURN() | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we keep the old
ITerminalHandoff
around? Isn't that just good practice?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This interface is essentially an internal currency between OpenConsole and the terminal. It doesn't need to support all interfaces. And after this PR OpenConsole will only support
ITerminalHandoff3
.But Dustin "Human Wikipedia" Howett explained me how stubs work and basically per user there can only be 1 single COM proxy stub instance for Windows Terminal. So, if the Windows Terminal Canary stub gets installed and it only supported
ITerminalHandoff3
then any older version of Windows Terminal that only supportsITerminalHandoff2
would not work anymore.However, there's some mapping from interface GUIs to proxies so it may just work to remove them anyway. He said we should just try it.