Merged PR 6285331: [Git2Git] Merged PR 6278637: Expose attached client process context to cooked read trace
Related work items: MSFT-32957145 Retrieved from https://microsoft.visualstudio.com os.2020 OS official/rs_wdx_dxp_windev bdb25dc99dcb2f1ee483dffe883d0178ea9d18dc
This commit is contained in:
parent
01b5195275
commit
184919fb24
|
@ -34,13 +34,13 @@ using Microsoft::Console::Interactivity::ServiceLocator;
|
|||
// - OriginalCursorPosition -
|
||||
// - NumberOfVisibleChars
|
||||
// - CtrlWakeupMask - Special client parameter to interrupt editing, end the wait, and return control to the client application
|
||||
// - CommandHistory -
|
||||
// - Echo -
|
||||
// - InsertMode -
|
||||
// - Processed -
|
||||
// - Line -
|
||||
// - pTempHandle - A handle to the output buffer to prevent it from being destroyed while we're using it to present 'edit line' text.
|
||||
// - initialData - any text data that should be prepopulated into the buffer
|
||||
// - pClientProcess - Attached process handle object
|
||||
// Return Value:
|
||||
// - THROW: Throws E_INVALIDARG for invalid pointers.
|
||||
COOKED_READ_DATA::COOKED_READ_DATA(_In_ InputBuffer* const pInputBuffer,
|
||||
|
@ -49,9 +49,9 @@ COOKED_READ_DATA::COOKED_READ_DATA(_In_ InputBuffer* const pInputBuffer,
|
|||
_In_ size_t UserBufferSize,
|
||||
_In_ PWCHAR UserBuffer,
|
||||
_In_ ULONG CtrlWakeupMask,
|
||||
_In_ CommandHistory* CommandHistory,
|
||||
const std::wstring_view exeName,
|
||||
const std::string_view initialData) :
|
||||
_In_ const std::wstring_view exeName,
|
||||
_In_ const std::string_view initialData,
|
||||
_In_ ConsoleProcessHandle* const pClientProcess) :
|
||||
ReadData(pInputBuffer, pInputReadHandleData),
|
||||
_screenInfo{ screenInfo },
|
||||
_bytesRead{ 0 },
|
||||
|
@ -62,7 +62,7 @@ COOKED_READ_DATA::COOKED_READ_DATA(_In_ InputBuffer* const pInputBuffer,
|
|||
_exeName{ exeName },
|
||||
_pdwNumBytes{ nullptr },
|
||||
|
||||
_commandHistory{ CommandHistory },
|
||||
_commandHistory{ CommandHistory::s_Find((HANDLE)pClientProcess) },
|
||||
_controlKeyState{ 0 },
|
||||
_ctrlWakeupMask{ CtrlWakeupMask },
|
||||
_visibleCharCount{ 0 },
|
||||
|
@ -73,7 +73,8 @@ COOKED_READ_DATA::COOKED_READ_DATA(_In_ InputBuffer* const pInputBuffer,
|
|||
_lineInput{ WI_IsFlagSet(pInputBuffer->InputMode, ENABLE_LINE_INPUT) },
|
||||
_processedInput{ WI_IsFlagSet(pInputBuffer->InputMode, ENABLE_PROCESSED_INPUT) },
|
||||
_insertMode{ ServiceLocator::LocateGlobals().getConsoleInformation().GetInsertMode() },
|
||||
_unicode{ false }
|
||||
_unicode{ false },
|
||||
_clientProcess{ pClientProcess }
|
||||
{
|
||||
#ifndef UNIT_TESTING
|
||||
THROW_IF_FAILED(screenInfo.GetMainBuffer().AllocateIoHandle(ConsoleHandleData::HandleType::Output,
|
||||
|
@ -1030,7 +1031,9 @@ void COOKED_READ_DATA::SavePendingInput(const size_t index, const bool multiline
|
|||
WI_IsFlagSet(gci.Flags, CONSOLE_HISTORY_NODUP)));
|
||||
}
|
||||
|
||||
Tracing::s_TraceCookedRead(_backupLimit, base::saturated_cast<ULONG>(StringLength));
|
||||
Tracing::s_TraceCookedRead(_clientProcess,
|
||||
_backupLimit,
|
||||
base::saturated_cast<ULONG>(StringLength));
|
||||
|
||||
// check for alias
|
||||
ProcessAliases(LineCount);
|
||||
|
|
|
@ -39,9 +39,9 @@ public:
|
|||
_In_ size_t UserBufferSize,
|
||||
_In_ PWCHAR UserBuffer,
|
||||
_In_ ULONG CtrlWakeupMask,
|
||||
_In_ CommandHistory* CommandHistory,
|
||||
const std::wstring_view exeName,
|
||||
const std::string_view initialData);
|
||||
_In_ const std::wstring_view exeName,
|
||||
_In_ const std::string_view initialData,
|
||||
_In_ ConsoleProcessHandle* const pClientProcess);
|
||||
|
||||
~COOKED_READ_DATA() override;
|
||||
COOKED_READ_DATA(COOKED_READ_DATA&&) = default;
|
||||
|
@ -156,6 +156,8 @@ private:
|
|||
bool _insertMode;
|
||||
bool _unicode;
|
||||
|
||||
ConsoleProcessHandle* const _clientProcess;
|
||||
|
||||
[[nodiscard]] NTSTATUS _readCharInputLoop(const bool isUnicode, size_t& numBytes) noexcept;
|
||||
|
||||
[[nodiscard]] NTSTATUS _handlePostCharInputLoop(const bool isUnicode, size_t& numBytes, ULONG& controlKeyState) noexcept;
|
||||
|
|
|
@ -471,7 +471,6 @@ size_t RetrieveNumberOfSpaces(_In_ SHORT sOriginalCursorPositionX,
|
|||
RETURN_HR_IF(E_FAIL, !gci.HasActiveOutputBuffer());
|
||||
|
||||
SCREEN_INFORMATION& screenInfo = gci.GetActiveOutputBuffer();
|
||||
CommandHistory* const pCommandHistory = CommandHistory::s_Find(processData);
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -481,9 +480,9 @@ size_t RetrieveNumberOfSpaces(_In_ SHORT sOriginalCursorPositionX,
|
|||
buffer.size_bytes(), // UserBufferSize
|
||||
reinterpret_cast<wchar_t*>(buffer.data()), // UserBuffer
|
||||
ctrlWakeupMask, // CtrlWakeupMask
|
||||
pCommandHistory, // CommandHistory
|
||||
exeName, // exe name
|
||||
initialData);
|
||||
initialData,
|
||||
reinterpret_cast<ConsoleProcessHandle*>(processData)); //pClientProcess
|
||||
|
||||
gci.SetCookedReadData(cookedReadData.get());
|
||||
bytesRead = buffer.size_bytes(); // This parameter on the way in is the size to read, on the way out, it will be updated to what is actually read.
|
||||
|
|
|
@ -406,42 +406,33 @@ void Tracing::s_TraceInputRecord(const INPUT_RECORD& inputRecord)
|
|||
}
|
||||
}
|
||||
|
||||
void Tracing::s_TraceCookedRead(_In_reads_(cchCookedBufferLength) const wchar_t* pwchCookedBuffer, _In_ ULONG cchCookedBufferLength)
|
||||
{
|
||||
TraceLoggingWrite(
|
||||
g_hConhostV2EventTraceProvider,
|
||||
"CookedRead",
|
||||
TraceLoggingCountedWideString(pwchCookedBuffer, cchCookedBufferLength, "ReadBuffer"),
|
||||
TraceLoggingULong(cchCookedBufferLength, "ReadBufferLength"),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE),
|
||||
TraceLoggingKeyword(TraceKeywords::CookedRead));
|
||||
void Tracing::s_TraceCookedRead(_In_ ConsoleProcessHandle* const pConsoleProcessHandle, _In_reads_(cchCookedBufferLength) const wchar_t* pwchCookedBuffer, _In_ ULONG cchCookedBufferLength)
|
||||
{
|
||||
if (TraceLoggingProviderEnabled(g_hConhostV2EventTraceProvider, 0, TraceKeywords::CookedRead)) {
|
||||
|
||||
TraceLoggingWrite(
|
||||
g_hConhostV2EventTraceProvider,
|
||||
"CookedRead",
|
||||
TraceLoggingCountedWideString(pwchCookedBuffer, cchCookedBufferLength, "ReadBuffer"),
|
||||
TraceLoggingULong(cchCookedBufferLength, "ReadBufferLength"),
|
||||
TraceLoggingUInt32(pConsoleProcessHandle->dwProcessId, "AttachedProcessId"),
|
||||
TraceLoggingUInt64(pConsoleProcessHandle->GetProcessCreationTime(), "AttachedProcessCreationTime"),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE),
|
||||
TraceLoggingKeyword(TraceKeywords::CookedRead));
|
||||
}
|
||||
}
|
||||
|
||||
void Tracing::s_TraceConsoleAttachDetach(_In_ const ConsoleProcessHandle* pConsoleProcessHandle, _In_ bool bIsAttach)
|
||||
{
|
||||
FILETIME ftCreationTime, ftDummyTime = { 0 };
|
||||
ULARGE_INTEGER creationTime = { 0 };
|
||||
|
||||
if (TraceLoggingProviderEnabled(g_hConhostV2EventTraceProvider,
|
||||
WINEVENT_LEVEL_LOG_ALWAYS,
|
||||
TraceKeywords::ConsoleAttachDetach)) {
|
||||
|
||||
if (::GetProcessTimes(pConsoleProcessHandle->GetRawHandle(),
|
||||
&ftCreationTime,
|
||||
&ftDummyTime,
|
||||
&ftDummyTime,
|
||||
&ftDummyTime)) {
|
||||
creationTime.HighPart = ftCreationTime.dwHighDateTime;
|
||||
creationTime.LowPart = ftCreationTime.dwLowDateTime;
|
||||
}
|
||||
|
||||
void Tracing::s_TraceConsoleAttachDetach(_In_ ConsoleProcessHandle* const pConsoleProcessHandle, _In_ bool bIsAttach)
|
||||
{
|
||||
if (TraceLoggingProviderEnabled(g_hConhostV2EventTraceProvider, 0, TraceKeywords::ConsoleAttachDetach)) {
|
||||
|
||||
bool bIsUserInteractive = Telemetry::Instance().IsUserInteractive();
|
||||
|
||||
TraceLoggingWrite(
|
||||
g_hConhostV2EventTraceProvider,
|
||||
"ConsoleAttachDetach",
|
||||
TraceLoggingUInt32(pConsoleProcessHandle->dwProcessId, "ProcessId"),
|
||||
TraceLoggingUInt64(creationTime.QuadPart, "ProcessCreationTime"),
|
||||
TraceLoggingUInt32(pConsoleProcessHandle->dwProcessId, "AttachedProcessId"),
|
||||
TraceLoggingUInt64(pConsoleProcessHandle->GetProcessCreationTime(), "AttachedProcessCreationTime"),
|
||||
TraceLoggingBool(bIsAttach, "IsAttach"),
|
||||
TraceLoggingBool(bIsUserInteractive, "IsUserInteractive"),
|
||||
TraceLoggingKeyword(TIL_KEYWORD_TRACE),
|
||||
|
|
|
@ -62,8 +62,8 @@ public:
|
|||
static void s_TraceWindowMessage(const MSG& msg);
|
||||
static void s_TraceInputRecord(const INPUT_RECORD& inputRecord);
|
||||
|
||||
static void s_TraceCookedRead(_In_reads_(cchCookedBufferLength) const wchar_t* pwchCookedBuffer, _In_ ULONG cchCookedBufferLength);
|
||||
static void s_TraceConsoleAttachDetach(_In_ const ConsoleProcessHandle* pConsoleProcessHandle, _In_ bool bIsAttach);
|
||||
static void s_TraceCookedRead(_In_ ConsoleProcessHandle* const pConsoleProcessHandle, _In_reads_(cchCookedBufferLength) const wchar_t* pwchCookedBuffer, _In_ ULONG cchCookedBufferLength);
|
||||
static void s_TraceConsoleAttachDetach(_In_ ConsoleProcessHandle* const pConsoleProcessHandle, _In_ bool bIsAttach);
|
||||
|
||||
static void __stdcall TraceFailure(const wil::FailureInfo& failure) noexcept;
|
||||
|
||||
|
|
|
@ -132,9 +132,9 @@ public:
|
|||
0,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr,
|
||||
L"",
|
||||
initialData);
|
||||
initialData,
|
||||
nullptr);
|
||||
gci.SetCookedReadData(readData);
|
||||
}
|
||||
|
||||
|
|
|
@ -312,7 +312,7 @@
|
|||
}
|
||||
CATCH_RETURN();
|
||||
|
||||
// ReadConsole needs this to get the command history list associated with an attached process, but it can be an opaque value.
|
||||
// ReadConsole needs this to get details associated with an attached process (such as the command history list, telemetry metadata).
|
||||
HANDLE const hConsoleClient = (HANDLE)m->GetProcessHandle();
|
||||
|
||||
// ReadConsole needs this to store context information across "processed reads" e.g. reads on the same handle
|
||||
|
|
|
@ -27,7 +27,8 @@ ConsoleProcessHandle::ConsoleProcessHandle(const DWORD dwProcessId,
|
|||
FALSE,
|
||||
dwProcessId))),
|
||||
_policy(ConsoleProcessPolicy::s_CreateInstance(_hProcess.get())),
|
||||
_shimPolicy(ConsoleShimPolicy::s_CreateInstance(_hProcess.get()))
|
||||
_shimPolicy(ConsoleShimPolicy::s_CreateInstance(_hProcess.get())),
|
||||
_processCreationTime(0)
|
||||
{
|
||||
if (nullptr != _hProcess.get())
|
||||
{
|
||||
|
@ -72,3 +73,28 @@ const HANDLE ConsoleProcessHandle::GetRawHandle() const
|
|||
{
|
||||
return _hProcess.get();
|
||||
}
|
||||
|
||||
// Routine Description:
|
||||
// - Retrieves the process creation time (currently used in telemetry traces)
|
||||
// - The creation time is lazily populated on first call
|
||||
const ULONG64 ConsoleProcessHandle::GetProcessCreationTime() const
|
||||
{
|
||||
if (_processCreationTime == 0 && _hProcess != nullptr) {
|
||||
|
||||
FILETIME ftCreationTime, ftDummyTime = { 0 };
|
||||
ULARGE_INTEGER creationTime = { 0 };
|
||||
|
||||
if (::GetProcessTimes(_hProcess.get(),
|
||||
&ftCreationTime,
|
||||
&ftDummyTime,
|
||||
&ftDummyTime,
|
||||
&ftDummyTime)) {
|
||||
creationTime.HighPart = ftCreationTime.dwHighDateTime;
|
||||
creationTime.LowPart = ftCreationTime.dwLowDateTime;
|
||||
}
|
||||
|
||||
_processCreationTime = creationTime.QuadPart;
|
||||
}
|
||||
|
||||
return _processCreationTime;
|
||||
}
|
||||
|
|
|
@ -44,6 +44,8 @@ public:
|
|||
|
||||
CD_CONNECTION_INFORMATION GetConnectionInformation(IDeviceComm* deviceComm) const;
|
||||
|
||||
const ULONG64 GetProcessCreationTime() const;
|
||||
|
||||
private:
|
||||
ConsoleProcessHandle(const DWORD dwProcessId,
|
||||
const DWORD dwThreadId,
|
||||
|
@ -58,6 +60,8 @@ private:
|
|||
ULONG const _ulProcessGroupId;
|
||||
wil::unique_handle const _hProcess;
|
||||
|
||||
mutable ULONG64 _processCreationTime;
|
||||
|
||||
const ConsoleProcessPolicy _policy;
|
||||
const ConsoleShimPolicy _shimPolicy;
|
||||
|
||||
|
|
Loading…
Reference in a new issue