// Copyright (c) Microsoft Corporation.// Licensed under the MIT license.#include "precomp.h"#include "VtInputThread.hpp"#include "../interactivity/inc/ServiceLocator.hpp"#include "input.h"#include "../terminal/parser/InputStateMachineEngine.hpp"#include "outputStream.hpp" // For ConhostInternalGetSet#include "../terminal/adapter/InteractDispatch.hpp"#include "../types/inc/convert.hpp"#include "server.h"#include "output.h"#include "handle.h"using namespace Microsoft::Console;// Constructor Description:// - Creates the VT Input Thread.// Arguments:// - hPipe - a handle to the file representing the read end of the VT pipe.// - inheritCursor - a bool indicating if the state machine should expect a// cursor positioning sequence. See MSFT:15681311.VtInputThread::VtInputThread(_In_ wil::unique_hfile hPipe,const bool inheritCursor) :_hFile{ std::move(hPipe) },_hThread{},_utf8Parser{ CP_UTF8 },_dwThreadId{ 0 },_exitRequested{ false },_exitResult{ S_OK }{THROW_HR_IF(E_HANDLE, _hFile.get() == INVALID_HANDLE_VALUE);CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();auto pGetSet = std::make_unique<ConhostInternalGetSet>(gci);THROW_IF_NULL_ALLOC(pGetSet.get());auto engine = std::make_unique<InputStateMachineEngine>(new InteractDispatch(pGetSet.release()), inheritCursor);THROW_IF_NULL_ALLOC(engine.get());_pInputStateMachine = std::make_unique<StateMachine>(engine.release());THROW_IF_NULL_ALLOC(_pInputStateMachine.get());}// Method Description:// - Processes a buffer of input characters. The characters should be utf-8// encoded, and will get converted to wchar_t's to be processed by the// input state machine.// Arguments:// - charBuffer - the UTF-8 characters recieved.// - cch - number of UTF-8 characters in charBuffer// Return Value:// - S_OK on success, otherwise an appropriate failure.[[nodiscard]]HRESULT VtInputThread::_HandleRunInput(_In_reads_(cch) const byte* const charBuffer, const int cch){// Make sure to call the GLOBAL Lock/Unlock, not the gci's lock/unlock.// Only the global unlock attempts to dispatch ctrl events. If you use the// gci's unlock, when you press C-c, it won't be dispatched until the// next console API call. For something like `powershell sleep 60`,// that won't happen for 60sLockConsole();auto Unlock = wil::scope_exit([&] { UnlockConsole(); });try{std::unique_ptr<wchar_t[]> pwsSequence;unsigned int cchConsumed;unsigned int cchSequence;auto hr = _utf8Parser.Parse(charBuffer, cch, cchConsumed, pwsSequence, cchSequence);// If we hit a parsing error, eat it. It's bad utf-8, we can't do anything with it.if (FAILED(hr)){return S_FALSE;}_pInputStateMachine->ProcessString(pwsSequence.get(), cchSequence);}CATCH_RETURN();return S_OK;}// Function Description:// - Static function used for initializing an instance's ThreadProc.// Arguments:// - lpParameter - A pointer to the VtInputThread instance that should be called.// Return Value:// - The return value of the underlying instance's _InputThreadDWORD VtInputThread::StaticVtInputThreadProc(_In_ LPVOID lpParameter){VtInputThread* const pInstance = reinterpret_cast<VtInputThread*>(lpParameter);return pInstance->_InputThread();}// Method Description:// - Do a single ReadFile from our pipe, and try and handle it. If handling// failed, throw or log, depending on what the caller wants.// Arguments:// - throwOnFail: If true, throw an exception if there was an error processing// the input recieved. Otherwise, log the error.// Return Value:// - <none>void VtInputThread::DoReadInput(const bool throwOnFail){byte buffer[256];DWORD dwRead = 0;bool fSuccess = !!ReadFile(_hFile.get(), buffer, ARRAYSIZE(buffer), &dwRead, nullptr);// If we failed to read because the terminal broke our pipe (usually due// to dying itself), close gracefully with ERROR_BROKEN_PIPE.// Otherwise throw an exception. ERROR_BROKEN_PIPE is the only case that// we want to gracefully close in.if (!fSuccess){_exitRequested = true;_exitResult = HRESULT_FROM_WIN32(GetLastError());return;}HRESULT hr = _HandleRunInput(buffer, dwRead);if (FAILED(hr)){if (throwOnFail){_exitResult = hr;_exitRequested = true;}else{LOG_IF_FAILED(hr);}}}// Method Description:// - The ThreadProc for the VT Input Thread. Reads input from the pipe, and// passes it to _HandleRunInput to be processed by the// InputStateMachineEngine.// Return Value:// - Any error from reading the pipe or writing to the input buffer that might// have caused us to exit.DWORD VtInputThread::_InputThread(){while (!_exitRequested){DoReadInput(true);}ServiceLocator::LocateGlobals().getConsoleInformation().GetVtIo()->CloseInput();return _exitResult;}// Method Description:// - Starts the VT input thread.[[nodiscard]]HRESULT VtInputThread::Start(){RETURN_HR_IF(E_HANDLE, !_hFile);HANDLE hThread = nullptr;// 0 is the right value, https://blogs.msdn.microsoft.com/oldnewthing/20040223-00/?p=40503DWORD dwThreadId = 0;hThread = CreateThread(nullptr,0,(LPTHREAD_START_ROUTINE)VtInputThread::StaticVtInputThreadProc,this,0,&dwThreadId);RETURN_LAST_ERROR_IF(hThread == INVALID_HANDLE_VALUE);_hThread.reset(hThread);_dwThreadId = dwThreadId;return S_OK;}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。