Skip to content
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

Make sure foreground access works for DefTerm #13247

Merged
11 commits merged into from
Jun 9, 2022
23 changes: 23 additions & 0 deletions src/cascadia/TerminalApp/TerminalPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,29 @@ namespace winrt::TerminalApp::implementation
// - see GH#2988
HRESULT TerminalPage::Initialize(HWND hwnd)
{
if (!_hostingHwnd.has_value())
{
// GH#13211 - if we haven't yet set the owning hwnd, reparent all the controls now.
for (const auto& tab : _tabs)
{
if (auto terminalTab{ _GetTerminalTabImpl(tab) })
{
terminalTab->GetRootPane()->WalkTree([&](auto&& pane) {
if (const auto& term{ pane->GetTerminalControl() })
{
term.OwningHwnd(reinterpret_cast<uint64_t>(hwnd));
}
});
}
// We don't need to worry about resetting the owning hwnd for the
// SUI here. GH#13211 only repros for a defterm connection, where
// the tab is spawned before the window is created. It's not
// possible to make a SUI tab like that, before the window is
// created. The SUI could be spawned as a part of a window restore,
// but that would still work fine. The window would be created
// before restoring previous tabs in that scenario.
}
}
_hostingHwnd = hwnd;
return S_OK;
}
Expand Down
21 changes: 19 additions & 2 deletions src/cascadia/TerminalControl/ControlCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,11 +289,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation
const auto height = vp.Height();
_connection.Resize(height, width);

if (_OwningHwnd != 0)
if (_owningHwnd != 0)
{
if (auto conpty{ _connection.try_as<TerminalConnection::ConptyConnection>() })
{
conpty.ReparentWindow(_OwningHwnd);
conpty.ReparentWindow(_owningHwnd);
}
}

Expand Down Expand Up @@ -1881,6 +1881,23 @@ namespace winrt::Microsoft::Terminal::Control::implementation
return Opacity() < 1.0f || UseAcrylic() || !_settings->BackgroundImage().empty() || _settings->UseBackgroundImageForWindow();
}

uint64_t ControlCore::OwningHwnd()
{
return _owningHwnd;
}

void ControlCore::OwningHwnd(uint64_t owner)
{
if (owner != _owningHwnd && _connection)
{
if (auto conpty{ _connection.try_as<TerminalConnection::ConptyConnection>() })
{
conpty.ReparentWindow(owner);
}
}
_owningHwnd = owner;
}

Windows::Foundation::Collections::IVector<Control::ScrollMark> ControlCore::ScrollMarks() const
{
auto internalMarks{ _terminal->GetScrollMarks() };
Expand Down
8 changes: 4 additions & 4 deletions src/cascadia/TerminalControl/ControlCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation

void WindowVisibilityChanged(const bool showOrHide);

// TODO:GH#1256 - When a tab can be torn out or otherwise reparented to
// another window, this value will need a custom setter, so that we can
// also update the connection.
WINRT_PROPERTY(uint64_t, OwningHwnd, 0);
uint64_t OwningHwnd();
void OwningHwnd(uint64_t owner);

RUNTIME_SETTING(double, Opacity, _settings->Opacity());
RUNTIME_SETTING(bool, UseAcrylic, _settings->UseAcrylic());
Expand Down Expand Up @@ -259,6 +257,8 @@ namespace winrt::Microsoft::Terminal::Control::implementation
double _panelHeight{ 0 };
double _compositionScale{ 0 };

uint64_t _owningHwnd{ 0 };

winrt::Windows::System::DispatcherQueue _dispatcher{ nullptr };
std::shared_ptr<ThrottledFuncTrailing<>> _tsfTryRedrawCanvas;
std::shared_ptr<ThrottledFuncTrailing<>> _updatePatternLocations;
Expand Down
6 changes: 6 additions & 0 deletions src/host/ConsoleArguments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ const std::wstring_view ConsoleArguments::FEATURE_ARG = L"--feature";
const std::wstring_view ConsoleArguments::FEATURE_PTY_ARG = L"pty";
const std::wstring_view ConsoleArguments::COM_SERVER_ARG = L"-Embedding";
const std::wstring_view ConsoleArguments::PASSTHROUGH_ARG = L"--passthrough";
// NOTE: Thinking about adding more commandline args that control conpty, for
// the Terminal? Make sure you add them to the commandline in
// ConsoleEstablishHandoff. We use that to initialize the ConsoleArguments for a
// defterm handoff s.t. they behave like a conpty connection that was started by
// the terminal. If you forget them there, the conpty won't obey them, only for
// defterm.

std::wstring EscapeArgument(std::wstring_view ac)
{
Expand Down
2 changes: 1 addition & 1 deletion src/host/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ void ProcessCtrlEvents()
if (NT_SUCCESS(Status))
{
Status = ServiceLocator::LocateConsoleControl()
->EndTask((HANDLE)rgProcessHandleList[i].dwProcessID,
->EndTask(rgProcessHandleList[i].dwProcessID,
EventType,
CtrlFlags);
if (rgProcessHandleList[i].hProcess == nullptr)
Expand Down
7 changes: 6 additions & 1 deletion src/host/srvinit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,12 @@ try
outPipeTheirSide.reset();
signalPipeTheirSide.reset();

const auto commandLine = fmt::format(FMT_COMPILE(L" --headless --signal {:#x}"), (int64_t)signalPipeOurSide.release());
// GH#13211 - Make sure we request win32input mode and that the terminal
// obeys the resizing quirk. Otherwise, defterm connections to the Terminal
// are going to have weird resizing, and aren't going to send full fidelity
// input messages.
const auto commandLine = fmt::format(FMT_COMPILE(L" --headless --resizeQuirk --win32input --signal {:#x}"),
(int64_t)signalPipeOurSide.release());

ConsoleArguments consoleArgs(commandLine, inPipeOurSide.release(), outPipeOurSide.release());
RETURN_IF_FAILED(consoleArgs.ParseCommandline());
Expand Down
8 changes: 4 additions & 4 deletions src/inc/HostSignals.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,21 @@ namespace Microsoft::Console
struct HostSignalNotifyAppData
{
uint32_t sizeInBytes;
uint32_t processId;
uint32_t processId; // THIS IS A PID
};

struct HostSignalSetForegroundData
{
uint32_t sizeInBytes;
uint32_t processId;
uint32_t processId; // THIS IS A HANDLE, NOT A PID
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blame @miniksa

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Brain fart. Sorry.

bool isForeground;
};

struct HostSignalEndTaskData
{
uint32_t sizeInBytes;
uint32_t processId;
uint32_t processId; // THIS IS A PID
uint32_t eventType;
uint32_t ctrlFlags;
};
};
};
8 changes: 5 additions & 3 deletions src/interactivity/base/HostSignalInputThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,17 +94,19 @@ T HostSignalInputThread::_ReceiveTypedPacket()
}
case HostSignals::SetForeground:
{
auto msg = _ReceiveTypedPacket<HostSignalSetForegroundData>();
_ReceiveTypedPacket<HostSignalSetForegroundData>();

LOG_IF_NTSTATUS_FAILED(ServiceLocator::LocateConsoleControl()->SetForeground(ULongToHandle(msg.processId), msg.isForeground));
// GH#13211 - This honestly shouldn't be called by OpenConsole
// anymore, but it's possible that a much older version of
// OpenConsole is still calling this. Just do nothing.

break;
}
case HostSignals::EndTask:
{
auto msg = _ReceiveTypedPacket<HostSignalEndTaskData>();

LOG_IF_NTSTATUS_FAILED(ServiceLocator::LocateConsoleControl()->EndTask(ULongToHandle(msg.processId), msg.eventType, msg.ctrlFlags));
LOG_IF_NTSTATUS_FAILED(ServiceLocator::LocateConsoleControl()->EndTask(msg.processId, msg.eventType, msg.ctrlFlags));

break;
}
Expand Down
14 changes: 6 additions & 8 deletions src/interactivity/base/RemoteConsoleControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,17 @@ template<typename T>

[[nodiscard]] NTSTATUS RemoteConsoleControl::SetForeground(_In_ HANDLE hProcess, _In_ BOOL fForeground)
{
HostSignalSetForegroundData data{};
data.sizeInBytes = sizeof(data);
data.processId = HandleToULong(hProcess);
data.isForeground = fForeground;

return _SendTypedPacket(_pipe.get(), HostSignals::SetForeground, data);
// GH#13211 - Apparently this API doesn't need to be forwarded to conhost at
// all. Instead, just perform the ConsoleControl operation here, in proc.
// This lets us avoid all sorts of strange handle duplicating weirdness.
return _control.SetForeground(hProcess, fForeground);
}

[[nodiscard]] NTSTATUS RemoteConsoleControl::EndTask(_In_ HANDLE hProcessId, _In_ DWORD dwEventType, _In_ ULONG ulCtrlFlags)
[[nodiscard]] NTSTATUS RemoteConsoleControl::EndTask(_In_ DWORD dwProcessId, _In_ DWORD dwEventType, _In_ ULONG ulCtrlFlags)
{
HostSignalEndTaskData data{};
data.sizeInBytes = sizeof(data);
data.processId = HandleToULong(hProcessId);
data.processId = dwProcessId;
data.eventType = dwEventType;
data.ctrlFlags = ulCtrlFlags;

Expand Down
5 changes: 4 additions & 1 deletion src/interactivity/base/RemoteConsoleControl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Author(s):
#pragma once

#include "../inc/IConsoleControl.hpp"
#include "../win32/ConsoleControl.hpp"

namespace Microsoft::Console::Interactivity
{
Expand All @@ -25,9 +26,11 @@ namespace Microsoft::Console::Interactivity
// IConsoleControl Members
[[nodiscard]] NTSTATUS NotifyConsoleApplication(_In_ DWORD dwProcessId);
[[nodiscard]] NTSTATUS SetForeground(_In_ HANDLE hProcess, _In_ BOOL fForeground);
[[nodiscard]] NTSTATUS EndTask(_In_ HANDLE hProcessId, _In_ DWORD dwEventType, _In_ ULONG ulCtrlFlags);
[[nodiscard]] NTSTATUS EndTask(_In_ DWORD dwProcessId, _In_ DWORD dwEventType, _In_ ULONG ulCtrlFlags);

private:
wil::unique_handle _pipe;

Win32::ConsoleControl _control;
};
}
2 changes: 1 addition & 1 deletion src/interactivity/inc/IConsoleControl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ namespace Microsoft::Console::Interactivity
virtual ~IConsoleControl() = default;
[[nodiscard]] virtual NTSTATUS NotifyConsoleApplication(DWORD dwProcessId) = 0;
[[nodiscard]] virtual NTSTATUS SetForeground(HANDLE hProcess, BOOL fForeground) = 0;
[[nodiscard]] virtual NTSTATUS EndTask(HANDLE hProcessId, DWORD dwEventType, ULONG ulCtrlFlags) = 0;
[[nodiscard]] virtual NTSTATUS EndTask(DWORD dwProcessId, DWORD dwEventType, ULONG ulCtrlFlags) = 0;
};
}
4 changes: 2 additions & 2 deletions src/interactivity/onecore/ConsoleControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ using namespace Microsoft::Console::Interactivity::OneCore;
return STATUS_SUCCESS;
}

[[nodiscard]] NTSTATUS ConsoleControl::EndTask(_In_ HANDLE hProcessId, _In_ DWORD dwEventType, _In_ ULONG ulCtrlFlags)
[[nodiscard]] NTSTATUS ConsoleControl::EndTask(_In_ DWORD dwProcessId, _In_ DWORD dwEventType, _In_ ULONG ulCtrlFlags)
{
USER_API_MSG m{};
const auto a = &m.u.EndTask;

RtlZeroMemory(a, sizeof(*a));
a->ProcessId = hProcessId;
a->ProcessId = ULongToHandle(dwProcessId); // This is actually a PID, even though the struct expects a HANDLE.
a->ConsoleEventCode = dwEventType;
a->ConsoleFlags = ulCtrlFlags;

Expand Down
2 changes: 1 addition & 1 deletion src/interactivity/onecore/ConsoleControl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ namespace Microsoft::Console::Interactivity::OneCore
// IConsoleControl Members
[[nodiscard]] NTSTATUS NotifyConsoleApplication(_In_ DWORD dwProcessId) noexcept override;
[[nodiscard]] NTSTATUS SetForeground(_In_ HANDLE hProcess, _In_ BOOL fForeground) noexcept override;
[[nodiscard]] NTSTATUS EndTask(_In_ HANDLE hProcessId, _In_ DWORD dwEventType, _In_ ULONG ulCtrlFlags) override;
[[nodiscard]] NTSTATUS EndTask(_In_ DWORD dwProcessId, _In_ DWORD dwEventType, _In_ ULONG ulCtrlFlags) override;
};
}
4 changes: 2 additions & 2 deletions src/interactivity/win32/ConsoleControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ using namespace Microsoft::Console::Interactivity::Win32;
sizeof(Flags));
}

[[nodiscard]] NTSTATUS ConsoleControl::EndTask(_In_ HANDLE hProcessId, _In_ DWORD dwEventType, _In_ ULONG ulCtrlFlags)
[[nodiscard]] NTSTATUS ConsoleControl::EndTask(_In_ DWORD dwProcessId, _In_ DWORD dwEventType, _In_ ULONG ulCtrlFlags)
{
auto pConsoleWindow = ServiceLocator::LocateConsoleWindow();

CONSOLEENDTASK ConsoleEndTaskParams;
ConsoleEndTaskParams.ProcessId = hProcessId;
ConsoleEndTaskParams.ProcessId = ULongToHandle(dwProcessId); // This is actually a PID, even though the struct expects a HANDLE.
ConsoleEndTaskParams.ConsoleEventCode = dwEventType;
ConsoleEndTaskParams.ConsoleFlags = ulCtrlFlags;
ConsoleEndTaskParams.hwnd = pConsoleWindow == nullptr ? nullptr : pConsoleWindow->GetWindowHandle();
Expand Down
2 changes: 1 addition & 1 deletion src/interactivity/win32/ConsoleControl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ namespace Microsoft::Console::Interactivity::Win32
// IConsoleControl Members
[[nodiscard]] NTSTATUS NotifyConsoleApplication(_In_ DWORD dwProcessId);
[[nodiscard]] NTSTATUS SetForeground(_In_ HANDLE hProcess, _In_ BOOL fForeground);
[[nodiscard]] NTSTATUS EndTask(_In_ HANDLE hProcessId, _In_ DWORD dwEventType, _In_ ULONG ulCtrlFlags);
[[nodiscard]] NTSTATUS EndTask(_In_ DWORD dwProcessId, _In_ DWORD dwEventType, _In_ ULONG ulCtrlFlags);

// Public Members
[[nodiscard]] NTSTATUS Control(_In_ ConsoleControl::ControlType ConsoleCommand,
Expand Down
2 changes: 1 addition & 1 deletion src/server/ProcessList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ void ConsoleProcessList::ModifyConsoleProcessFocus(const bool fForeground)
{
const auto pProcessHandle = *it;

if (pProcessHandle->_hProcess != nullptr)
if (pProcessHandle->_hProcess)
{
_ModifyProcessForegroundRights(pProcessHandle->_hProcess.get(), fForeground);
}
Expand Down