in src/agent/Scraper.cc [319:387]
void Scraper::syncConsoleContentAndSize(
bool forceResize,
ConsoleScreenBufferInfo &finalInfoOut)
{
// We'll try to avoid freezing the console by reading large chunks (or
// all!) of the screen buffer without otherwise attempting to synchronize
// with the console application. We can only do this on Windows 10 and up
// because:
// - Prior to Windows 8, the size of a ReadConsoleOutputW call was limited
// by the ~32KB RPC buffer.
// - Prior to Windows 10, an out-of-range read region crashes the caller.
// (See misc/WindowsBugCrashReader.cc.)
//
if (!m_console.isNewW10() || forceResize) {
m_console.setFrozen(true);
}
const ConsoleScreenBufferInfo info = m_consoleBuffer->bufferInfo();
bool cursorVisible = true;
CONSOLE_CURSOR_INFO cursorInfo = {};
if (!GetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursorInfo)) {
trace("GetConsoleCursorInfo failed");
} else {
cursorVisible = cursorInfo.bVisible != 0;
}
// If an app resizes the buffer height, then we enter "direct mode", where
// we stop trying to track incremental console changes.
const bool newDirectMode = (info.bufferSize().Y != BUFFER_LINE_COUNT);
if (newDirectMode != m_directMode) {
trace("Entering %s mode", newDirectMode ? "direct" : "scrolling");
resetConsoleTracking(Terminal::SendClear,
newDirectMode ? 0 : info.windowRect().top());
m_directMode = newDirectMode;
// When we switch from direct->scrolling mode, make sure the console is
// the right size.
if (!m_directMode) {
m_console.setFrozen(true);
forceResize = true;
}
}
if (m_directMode) {
// In direct-mode, resizing the console redraws the terminal, so do it
// before scraping.
if (forceResize) {
resizeImpl(info);
}
directScrapeOutput(info, cursorVisible);
} else {
if (!m_console.frozen()) {
if (!scrollingScrapeOutput(info, cursorVisible, true)) {
m_console.setFrozen(true);
}
}
if (m_console.frozen()) {
scrollingScrapeOutput(info, cursorVisible, false);
}
// In scrolling mode, we want to scrape before resizing, because we'll
// erase everything in the console buffer up to the top of the console
// window.
if (forceResize) {
resizeImpl(info);
}
}
finalInfoOut = forceResize ? m_consoleBuffer->bufferInfo() : info;
}