Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/actions/spelling/expect/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1988,3 +1988,4 @@ ZCtrl
zero'd
ZWJs
ZYXWVUTd
XTVERSION
1 change: 1 addition & 0 deletions doc/reference/master-sequence-list.csv
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"DA1","","Primary Device Attributes","`VT100`","Terminal Management Functions","Identification, status, and Initialization","","",""
"DA2","","Secondary Device Attributes","`VT220`","Terminal Management Functions","Identification, status, and Initialization","","",""
"DA3","","Tertiary Device Attributes","`VT420`","Terminal Management Functions","Identification, status, and Initialization","","",""
"XTVERSION","","Report Terminal Name and Version","`XTerm`","Terminal Management Functions","Identification, status, and Initialization","","",""
"DSR","","Device Status Report","`VT100`","Terminal Management Functions","Identification, status, and Initialization","","",""
"DECID","","Identify Device","`VT100`","Terminal Management Functions","Identification, status, and Initialization","","",""
"DECTID","","Select Terminal ID","`VT510`","Terminal Management Functions","Identification, status, and Initialization","","",""
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalCore/Terminal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@ class Microsoft::Terminal::Core::Terminal final :

void SearchMissingCommand(const std::wstring_view command) override;

std::wstring_view GetHostIdentity() const override;

#pragma endregion

void ClearMark();
Expand Down
20 changes: 20 additions & 0 deletions src/cascadia/TerminalCore/TerminalApi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "tracing.hpp"

#include "../src/inc/unicode.hpp"
#include <winrt/Windows.ApplicationModel.h>

using namespace Microsoft::Terminal::Core;
using namespace Microsoft::Console::Render;
Expand Down Expand Up @@ -421,3 +422,22 @@ void Terminal::NotifyShellIntegrationMark()
// Notify the scrollbar that marks have been added so it can refresh the mark indicators
_NotifyScrollEvent();
}

std::wstring_view Terminal::GetHostIdentity() const
{
static const auto identity = []() -> std::wstring {
try
{
auto package = winrt::Windows::ApplicationModel::Package::Current();
auto version = package.Id().Version();
return fmt::format(FMT_COMPILE(L"Windows Terminal {}.{}.{}.{}"), version.Major, version.Minor, version.Build, version.Revision);
}
catch (...)
{
// Not packaged or other error - return fixed name
return L"Windows Terminal";
}
}();

return identity;
}
5 changes: 5 additions & 0 deletions src/host/outputStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -459,3 +459,8 @@ void ConhostInternalGetSet::SearchMissingCommand(std::wstring_view /*missingComm
{
// Not implemented for conhost.
}

std::wstring_view ConhostInternalGetSet::GetHostIdentity() const
{
return L"Windows Console Host";

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

For ConHost, could we not perhaps pull a version number from GetFileVersionInfo? Maybe also do something with the module name to differentiate between OpenConsole and inbox ConHost (I suspect they're using completely different version schemes).

If not, I think it might be better to just ignore XTVERSION requests altogether, because returning a name without a version will likely just be used to blacklist ConHost.

}
2 changes: 2 additions & 0 deletions src/host/outputStream.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ class ConhostInternalGetSet final : public Microsoft::Console::VirtualTerminal::

void SearchMissingCommand(std::wstring_view missingCommand) override;

std::wstring_view GetHostIdentity() const override;

private:
Microsoft::Console::IIoProvider& _io;
};
1 change: 1 addition & 0 deletions src/terminal/adapter/ITermDispatch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ class Microsoft::Console::VirtualTerminal::ITermDispatch
virtual void DeviceAttributes() = 0; // DA1
virtual void SecondaryDeviceAttributes() = 0; // DA2
virtual void TertiaryDeviceAttributes() = 0; // DA3
virtual void RequestTerminalNameVersion() = 0; // XTVERSION
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
virtual void Vt52DeviceAttributes() = 0; // VT52 Identify
virtual void RequestTerminalParameters(const DispatchTypes::ReportingPermission permission) = 0; // DECREQTPARM

Expand Down
2 changes: 2 additions & 0 deletions src/terminal/adapter/ITerminalApi.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,5 +92,7 @@ namespace Microsoft::Console::VirtualTerminal
virtual void InvokeCompletions(std::wstring_view menuJson, unsigned int replaceLength) = 0;

virtual void SearchMissingCommand(const std::wstring_view command) = 0;

virtual std::wstring_view GetHostIdentity() const = 0;
};
}
11 changes: 11 additions & 0 deletions src/terminal/adapter/adaptDispatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1483,6 +1483,17 @@ void AdaptDispatch::TertiaryDeviceAttributes()
_ReturnDcsResponse(L"!|00000000");
}

// Routine Description:
// - XTVERSION - Reports the name and version of the host application.
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
// The response format is DCS > | text ST. The host identity is determined
// by the host implementation via ITerminalApi::GetHostIdentity().
// Arguments:
// - <none>
void AdaptDispatch::RequestTerminalNameVersion()
{
_ReturnDcsResponse(fmt::format(FMT_COMPILE(L">|{}"), _api.GetHostIdentity()));
}

// Routine Description:
// - VT52 Identify - Reports the identity of the terminal in VT52 emulation mode.
// An actual VT52 terminal would typically identify itself with ESC / K.
Expand Down
1 change: 1 addition & 0 deletions src/terminal/adapter/adaptDispatch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ namespace Microsoft::Console::VirtualTerminal
void DeviceAttributes() override; // DA1
void SecondaryDeviceAttributes() override; // DA2
void TertiaryDeviceAttributes() override; // DA3
void RequestTerminalNameVersion() override; // XTVERSION
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
void Vt52DeviceAttributes() override; // VT52 Identify
void RequestTerminalParameters(const DispatchTypes::ReportingPermission permission) override; // DECREQTPARM
void ScrollUp(const VTInt distance) override; // SU
Expand Down
1 change: 1 addition & 0 deletions src/terminal/adapter/termDispatch.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ class Microsoft::Console::VirtualTerminal::TermDispatch : public Microsoft::Cons
void DeviceAttributes() override {} // DA1
void SecondaryDeviceAttributes() override {} // DA2
void TertiaryDeviceAttributes() override {} // DA3
void RequestTerminalNameVersion() override {} // XTVERSION
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
void Vt52DeviceAttributes() override {} // VT52 Identify
void RequestTerminalParameters(const DispatchTypes::ReportingPermission /*permission*/) override {} // DECREQTPARM

Expand Down
30 changes: 30 additions & 0 deletions src/terminal/adapter/ut_adapter/adapterTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,11 @@ class TestGetSet final : public ITerminalApi
Log::Comment(L"SearchMissingCommand MOCK called...");
}

std::wstring_view GetHostIdentity() const override
{
return _hostIdentity;
}

void PrepData()
{
PrepData(CursorDirection::UP); // if called like this, the cursor direction doesn't matter.
Expand Down Expand Up @@ -402,6 +407,8 @@ class TestGetSet final : public ITerminalApi
std::wstring _expectedMenuJson{};
unsigned int _expectedReplaceLength = 0;

std::wstring_view _hostIdentity{ L"Windows Console Host" };

private:
HANDLE _hCon;
};
Expand Down Expand Up @@ -1796,6 +1803,23 @@ class AdapterTest
VERIFY_THROWS(_pDispatch->TertiaryDeviceAttributes(), std::exception);
}

TEST_METHOD(RequestTerminalNameVersionTests)
{
Log::Comment(L"Starting test...");

// The test runner is unpackaged, so no package version is available.
Log::Comment(L"Test 1: Verify normal response.");
_testGetSet->PrepData();
_pDispatch->RequestTerminalNameVersion();
_testGetSet->ValidateInputEvent(L"\x1bP>|Windows Console Host\x1b\\");

Log::Comment(L"Test 2: Verify failure when ReturnResponse doesn't work.");
_testGetSet->PrepData();
_testGetSet->_returnResponseResult = FALSE;

VERIFY_THROWS(_pDispatch->RequestTerminalNameVersion(), std::exception);
}

TEST_METHOD(RequestDisplayedExtentTests)
{
Log::Comment(L"Starting test...");
Expand Down Expand Up @@ -4010,6 +4034,9 @@ class AdapterTest
_pDispatch->TertiaryDeviceAttributes();
_testGetSet->ValidateInputEvent(L"\x90!|00000000\x9c");

_pDispatch->RequestTerminalNameVersion();
_testGetSet->ValidateInputEvent(L"\x90>|Windows Console Host\x9c");

_pDispatch->RequestColorTableEntry(0);
_testGetSet->ValidateInputEvent(L"\x9d\x34;0;rgb:0c0c/0c0c/0c0c\x9c");

Expand All @@ -4022,6 +4049,9 @@ class AdapterTest
_pDispatch->TertiaryDeviceAttributes();
_testGetSet->ValidateInputEvent(L"\x1bP!|00000000\x1b\\");

_pDispatch->RequestTerminalNameVersion();
_testGetSet->ValidateInputEvent(L"\x1bP>|Windows Console Host\x1b\\");

_pDispatch->RequestColorTableEntry(0);
_testGetSet->ValidateInputEvent(L"\x1b]4;0;rgb:0c0c/0c0c/0c0c\x1b\\");
}
Expand Down
6 changes: 6 additions & 0 deletions src/terminal/parser/OutputStateMachineEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,12 @@ bool OutputStateMachineEngine::ActionCsiDispatch(const VTID id, const VTParamete
_dispatch->TertiaryDeviceAttributes();
}
break;
case CsiActionCodes::XT_RequestVersion:
if (parameters.at(0).value_or(0) == 0)
{
_dispatch->RequestTerminalNameVersion();
}
break;
case CsiActionCodes::DECREQTPARM_RequestTerminalParameters:
_dispatch->RequestTerminalParameters(parameters.at(0));
break;
Expand Down
1 change: 1 addition & 0 deletions src/terminal/parser/OutputStateMachineEngine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ namespace Microsoft::Console::VirtualTerminal
SGR_SetGraphicsRendition = VTID("m"),
DSR_DeviceStatusReport = VTID("n"),
DSR_PrivateDeviceStatusReport = VTID("?n"),
XT_RequestVersion = VTID(">q"),
DECSTBM_SetTopBottomMargins = VTID("r"),
DECSLRM_SetLeftRightMargins = VTID("s"),
DTTERM_WindowManipulation = VTID("t"), // NOTE: Overlaps with DECSLPP. Fix when/if implemented.
Expand Down
47 changes: 47 additions & 0 deletions src/terminal/parser/ut_parser/OutputEngineTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1142,6 +1142,7 @@ class StatefulDispatch final : public TermDispatch
_deviceAttributes{ false },
_secondaryDeviceAttributes{ false },
_tertiaryDeviceAttributes{ false },
_requestTerminalNameVersion{ false },
_vt52DeviceAttributes{ false },
_requestTerminalParameters{ false },
_reportingPermission{ (DispatchTypes::ReportingPermission)-1 },
Expand Down Expand Up @@ -1308,6 +1309,11 @@ class StatefulDispatch final : public TermDispatch
_tertiaryDeviceAttributes = true;
}

void RequestTerminalNameVersion() noexcept override
{
_requestTerminalNameVersion = true;
}

void Vt52DeviceAttributes() noexcept override
{
_vt52DeviceAttributes = true;
Expand Down Expand Up @@ -1472,6 +1478,7 @@ class StatefulDispatch final : public TermDispatch
bool _deviceAttributes;
bool _secondaryDeviceAttributes;
bool _tertiaryDeviceAttributes;
bool _requestTerminalNameVersion;
bool _vt52DeviceAttributes;
bool _requestTerminalParameters;
DispatchTypes::ReportingPermission _reportingPermission;
Expand Down Expand Up @@ -2392,6 +2399,46 @@ class StateMachineExternalTest final
pDispatch->ClearState();
}

TEST_METHOD(TestRequestTerminalNameVersion)
{
auto dispatch = std::make_unique<StatefulDispatch>();
auto pDispatch = dispatch.get();
auto engine = std::make_unique<OutputStateMachineEngine>(std::move(dispatch));
StateMachine mach(std::move(engine));

Log::Comment(L"Test 1: Check default case, no params.");
mach.ProcessCharacter(AsciiChars::ESC);
mach.ProcessCharacter(L'[');
mach.ProcessCharacter(L'>');
mach.ProcessCharacter(L'q');

VERIFY_IS_TRUE(pDispatch->_requestTerminalNameVersion);

pDispatch->ClearState();

Log::Comment(L"Test 2: Check default case, 0 param.");
mach.ProcessCharacter(AsciiChars::ESC);
mach.ProcessCharacter(L'[');
mach.ProcessCharacter(L'>');
mach.ProcessCharacter(L'0');
mach.ProcessCharacter(L'q');

VERIFY_IS_TRUE(pDispatch->_requestTerminalNameVersion);

pDispatch->ClearState();

Log::Comment(L"Test 3: Check fail case, 1 (or any other) param.");
mach.ProcessCharacter(AsciiChars::ESC);
mach.ProcessCharacter(L'[');
mach.ProcessCharacter(L'>');
mach.ProcessCharacter(L'1');
mach.ProcessCharacter(L'q');

VERIFY_IS_FALSE(pDispatch->_requestTerminalNameVersion);

pDispatch->ClearState();
}

TEST_METHOD(TestRequestTerminalParameters)
{
auto dispatch = std::make_unique<StatefulDispatch>();
Expand Down
Loading