/*++ Copyright (c) Microsoft Corporation Licensed under the MIT license. Module Name: - ConsoleArguments.hpp Abstract: - Encapsulates the commandline arguments to the console host. Author(s): - Mike Griese (migrie) 07-Sept-2017 --*/ #pragma once #ifdef UNIT_TESTING #include "WexTestClass.h" #endif class ConsoleArguments { public: ConsoleArguments(const std::wstring& commandline, const HANDLE hStdIn, const HANDLE hStdOut); ConsoleArguments(); ConsoleArguments& operator=(const ConsoleArguments& other); [[nodiscard]] HRESULT ParseCommandline(); bool HasVtHandles() const; bool InConptyMode() const noexcept; bool IsHeadless() const; bool ShouldCreateServerHandle() const; HANDLE GetServerHandle() const; HANDLE GetVtInHandle() const; HANDLE GetVtOutHandle() const; bool HasSignalHandle() const; HANDLE GetSignalHandle() const; std::wstring GetClientCommandline() const; std::wstring GetVtMode() const; bool GetForceV1() const; short GetWidth() const; short GetHeight() const; bool GetInheritCursor() const; void SetExpectedSize(COORD dimensions) noexcept; #ifdef UNIT_TESTING void EnableConptyModeForTests(); #endif static const std::wstring_view VT_MODE_ARG; static const std::wstring_view HEADLESS_ARG; static const std::wstring_view SERVER_HANDLE_ARG; static const std::wstring_view SIGNAL_HANDLE_ARG; static const std::wstring_view HANDLE_PREFIX; static const std::wstring_view CLIENT_COMMANDLINE_ARG; static const std::wstring_view FORCE_V1_ARG; static const std::wstring_view FILEPATH_LEADER_PREFIX; static const std::wstring_view WIDTH_ARG; static const std::wstring_view HEIGHT_ARG; static const std::wstring_view INHERIT_CURSOR_ARG; static const std::wstring_view FEATURE_ARG; static const std::wstring_view FEATURE_PTY_ARG; private: #ifdef UNIT_TESTING // This accessor used to create a copy of this class for unit testing comparison ease. ConsoleArguments(const std::wstring commandline, const std::wstring clientCommandline, const HANDLE vtInHandle, const HANDLE vtOutHandle, const std::wstring vtMode, const short width, const short height, const bool forceV1, const bool headless, const bool createServerHandle, const DWORD serverHandle, const DWORD signalHandle, const bool inheritCursor) : _commandline(commandline), _clientCommandline(clientCommandline), _vtInHandle(vtInHandle), _vtOutHandle(vtOutHandle), _vtMode(vtMode), _width(width), _height(height), _forceV1(forceV1), _headless(headless), _createServerHandle(createServerHandle), _serverHandle(serverHandle), _signalHandle(signalHandle), _inheritCursor(inheritCursor), _receivedEarlySizeChange{ false }, _originalWidth{ -1 }, _originalHeight{ -1 } { } #endif std::wstring _commandline; std::wstring _clientCommandline; HANDLE _vtInHandle; HANDLE _vtOutHandle; std::wstring _vtMode; bool _forceV1; bool _headless; short _width; short _height; bool _createServerHandle; DWORD _serverHandle; DWORD _signalHandle; bool _inheritCursor; bool _receivedEarlySizeChange; short _originalWidth; short _originalHeight; [[nodiscard]] HRESULT _GetClientCommandline(_Inout_ std::vector& args, const size_t index, const bool skipFirst); static void s_ConsumeArg(_Inout_ std::vector& args, _In_ size_t& index); [[nodiscard]] static HRESULT s_GetArgumentValue(_Inout_ std::vector& args, _Inout_ size_t& index, _Out_opt_ std::wstring* const pSetting); [[nodiscard]] static HRESULT s_GetArgumentValue(_Inout_ std::vector& args, _Inout_ size_t& index, _Out_opt_ short* const pSetting); [[nodiscard]] static HRESULT s_HandleFeatureValue(_Inout_ std::vector& args, _Inout_ size_t& index); [[nodiscard]] static HRESULT s_ParseHandleArg(const std::wstring& handleAsText, _Inout_ DWORD& handleAsVal); #ifdef UNIT_TESTING friend class ConsoleArgumentsTests; #endif }; #ifdef UNIT_TESTING namespace WEX { namespace TestExecution { template<> class VerifyOutputTraits { public: static WEX::Common::NoThrowString ToString(const ConsoleArguments& ci) { return WEX::Common::NoThrowString().Format(L"\r\nClient Command Line: '%ws',\r\n" L"Use VT Handles: '%ws',\r\n" L"VT In Handle: '0x%x',\r\n" L"VT Out Handle: '0x%x',\r\n" L"Vt Mode: '%ws',\r\n" L"WidthxHeight: '%dx%d',\r\n" L"ForceV1: '%ws',\r\n" L"Headless: '%ws',\r\n" L"Create Server Handle: '%ws',\r\n" L"Server Handle: '0x%x'\r\n" L"Use Signal Handle: '%ws'\r\n" L"Signal Handle: '0x%x'\r\n", L"Inherit Cursor: '%ws'\r\n", ci.GetClientCommandline().c_str(), s_ToBoolString(ci.HasVtHandles()), ci.GetVtInHandle(), ci.GetVtOutHandle(), ci.GetVtMode().c_str(), ci.GetWidth(), ci.GetHeight(), s_ToBoolString(ci.GetForceV1()), s_ToBoolString(ci.IsHeadless()), s_ToBoolString(ci.ShouldCreateServerHandle()), ci.GetServerHandle(), s_ToBoolString(ci.HasSignalHandle()), ci.GetSignalHandle(), s_ToBoolString(ci.GetInheritCursor())); } private: static PCWSTR s_ToBoolString(const bool val) { return val ? L"true" : L"false"; } }; template<> class VerifyCompareTraits { public: static bool AreEqual(const ConsoleArguments& expected, const ConsoleArguments& actual) { return expected.GetClientCommandline() == actual.GetClientCommandline() && expected.HasVtHandles() == actual.HasVtHandles() && expected.GetVtInHandle() == actual.GetVtInHandle() && expected.GetVtOutHandle() == actual.GetVtOutHandle() && expected.GetVtMode() == actual.GetVtMode() && expected.GetWidth() == actual.GetWidth() && expected.GetHeight() == actual.GetHeight() && expected.GetForceV1() == actual.GetForceV1() && expected.IsHeadless() == actual.IsHeadless() && expected.ShouldCreateServerHandle() == actual.ShouldCreateServerHandle() && expected.GetServerHandle() == actual.GetServerHandle() && expected.HasSignalHandle() == actual.HasSignalHandle() && expected.GetSignalHandle() == actual.GetSignalHandle() && expected.GetInheritCursor() == actual.GetInheritCursor(); } static bool AreSame(const ConsoleArguments& expected, const ConsoleArguments& actual) { return &expected == &actual; } static bool IsLessThan(const ConsoleArguments&, const ConsoleArguments&) = delete; static bool IsGreaterThan(const ConsoleArguments&, const ConsoleArguments&) = delete; static bool IsNull(const ConsoleArguments& object) { return object.GetClientCommandline().empty() && (object.GetVtInHandle() == 0 || object.GetVtInHandle() == INVALID_HANDLE_VALUE) && (object.GetVtOutHandle() == 0 || object.GetVtOutHandle() == INVALID_HANDLE_VALUE) && object.GetVtMode().empty() && !object.GetForceV1() && (object.GetWidth() == 0) && (object.GetHeight() == 0) && !object.IsHeadless() && !object.ShouldCreateServerHandle() && object.GetServerHandle() == 0 && (object.GetSignalHandle() == 0 || object.GetSignalHandle() == INVALID_HANDLE_VALUE) && !object.GetInheritCursor(); } }; } } #endif