// Copyright (c) Microsoft Corporation.// Licensed under the MIT license.#include "precomp.h"#include "readDataDirect.hpp"#include "dbcs.h"#include "misc.h"#include "..\interactivity\inc\ServiceLocator.hpp"// Routine Description:// - Constructs direct read data class to hold context across sessions// generally when there's not enough data to return. Also used a bit// internally to just pass some information along the stack// (regardless of wait necessity).// Arguments:// - pInputBuffer - Buffer that data will be read from.// - pInputReadHandleData - Context stored across calls from the same// input handle to return partial data appropriately.// the user's buffer (pOutRecords)// - eventReadCount - the number of events to read// - partialEvents - any partial events already read// Return Value:// - THROW: Throws E_INVALIDARG for invalid pointers.DirectReadData::DirectReadData(_In_ InputBuffer* const pInputBuffer,_In_ INPUT_READ_HANDLE_DATA* const pInputReadHandleData,const size_t eventReadCount,_In_ std::deque<std::unique_ptr<IInputEvent>> partialEvents) :ReadData(pInputBuffer, pInputReadHandleData),_eventReadCount{ eventReadCount },_partialEvents{ std::move(partialEvents) },_outEvents{ }{}// Routine Description:// - Destructs a read data class.// - Decrements count of readers waiting on the given handle.DirectReadData::~DirectReadData(){}// Routine Description:// - This routine is called to complete a direct read that blocked in// ReadInputBuffer. The context of the read was saved in the DirectReadData// structure. This routine is called when events have been written to// the input buffer. It is called in the context of the writing thread.// Arguments:// - TerminationReason - if this routine is called because a ctrl-c or// ctrl-break was seen, this argument contains CtrlC or CtrlBreak. If// the owning thread is exiting, it will have ThreadDying. Otherwise 0.// - fIsUnicode - Should we return UCS-2 unicode data, or should we// run the final data through the current Input Codepage before// returning?// - pReplyStatus - The status code to return to the client// application that originally called the API (before it was queued to// wait)// - pNumBytes - not used// - pControlKeyState - For certain types of reads, this specifies// which modifier keys were held.// - pOutputData - a pointer to a// std::deque<std::unique_ptr<IInputEvent>> that is used to the read// input events back to the server// Return Value:// - true if the wait is done and result buffer/status code can be sent back to the client.// - false if we need to continue to wait until more data is available.bool DirectReadData::Notify(const WaitTerminationReason TerminationReason,const bool fIsUnicode,_Out_ NTSTATUS* const pReplyStatus,_Out_ size_t* const pNumBytes,_Out_ DWORD* const pControlKeyState,_Out_ void* const pOutputData){FAIL_FAST_IF_NULL(pOutputData);FAIL_FAST_IF(_pInputReadHandleData->GetReadCount() == 0);const CONSOLE_INFORMATION& gci = ServiceLocator::LocateGlobals().getConsoleInformation();FAIL_FAST_IF(!gci.IsConsoleLocked());*pReplyStatus = STATUS_SUCCESS;*pControlKeyState = 0;*pNumBytes = 0;bool retVal = true;std::deque<std::unique_ptr<IInputEvent>> readEvents;// If ctrl-c or ctrl-break was seen, ignore it.if (WI_IsAnyFlagSet(TerminationReason, (WaitTerminationReason::CtrlC | WaitTerminationReason::CtrlBreak))){return false;}// check if a partial byte is already stored that we should readif (!fIsUnicode &&_pInputBuffer->IsReadPartialByteSequenceAvailable() &&_eventReadCount == 1){_partialEvents.push_back(_pInputBuffer->FetchReadPartialByteSequence(false));}// See if called by CsrDestroyProcess or CsrDestroyThread// via ConsoleNotifyWaitBlock. If so, just decrement the ReadCount and return.if (WI_IsFlagSet(TerminationReason, WaitTerminationReason::ThreadDying)){*pReplyStatus = STATUS_THREAD_IS_TERMINATING;}// We must see if we were woken up because the handle is being// closed. If so, we decrement the read count. If it goes to// zero, we wake up the close thread. Otherwise, we wake up any// other thread waiting for data.else if (WI_IsFlagSet(TerminationReason, WaitTerminationReason::HandleClosing)){*pReplyStatus = STATUS_ALERTED;}else{// if we get to here, this routine was called either by the input// thread or a write routine. both of these callers grab the// current console lock.// calculate how many events we need to readsize_t amountAlreadyRead;if (FAILED(SizeTAdd(_partialEvents.size(), _outEvents.size(), &amountAlreadyRead))){*pReplyStatus = STATUS_INTEGER_OVERFLOW;return retVal;}size_t amountToRead;if (FAILED(SizeTSub(_eventReadCount, amountAlreadyRead, &amountToRead))){*pReplyStatus = STATUS_INTEGER_OVERFLOW;return retVal;}*pReplyStatus = _pInputBuffer->Read(readEvents,amountToRead,false,false,fIsUnicode,false);if (*pReplyStatus == CONSOLE_STATUS_WAIT){retVal = false;}}if (*pReplyStatus != CONSOLE_STATUS_WAIT){// split key events to oem chars if necessaryif (*pReplyStatus == STATUS_SUCCESS && !fIsUnicode){try{SplitToOem(readEvents);}CATCH_LOG();}// combine partial and whole eventswhile (!_partialEvents.empty()){readEvents.push_front(std::move(_partialEvents.back()));_partialEvents.pop_back();}// move read events to out storagefor (size_t i = 0; i < _eventReadCount; ++i){if (readEvents.empty()){break;}_outEvents.push_back(std::move(readEvents.front()));readEvents.pop_front();}// store partial event if necessaryif (!readEvents.empty()){_pInputBuffer->StoreReadPartialByteSequence(std::move(readEvents.front()));readEvents.pop_front();FAIL_FAST_IF(!(readEvents.empty()));}// move events to pOutputDatastd::deque<std::unique_ptr<IInputEvent>>* const pOutputDeque = reinterpret_cast<std::deque<std::unique_ptr<IInputEvent>>* const>(pOutputData);*pNumBytes = _outEvents.size() * sizeof(INPUT_RECORD);pOutputDeque->swap(_outEvents);}return retVal;}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。