https://git.reactos.org/?p=reactos.git;a=commitdiff;h=9337ea6a3c6b93837a02ca...
commit 9337ea6a3c6b93837a02ca83dd2d8899d40d7072 Author: Hermès Bélusca-Maïto hermes.belusca-maito@reactos.org AuthorDate: Mon Nov 21 16:35:47 2022 +0100 Commit: Hermès Bélusca-Maïto hermes.belusca-maito@reactos.org CommitDate: Tue Nov 22 02:10:54 2022 +0100
[NTOS:KDBG] Deduplicate code between KdbpPrint() and KdbpPager(). --- ntoskrnl/kdbg/kdb.h | 9 +- ntoskrnl/kdbg/kdb_cli.c | 548 ++++++++++++++++++------------------------------ 2 files changed, 207 insertions(+), 350 deletions(-)
diff --git a/ntoskrnl/kdbg/kdb.h b/ntoskrnl/kdbg/kdb.h index 542cc398f11..d78e2696cdd 100644 --- a/ntoskrnl/kdbg/kdb.h +++ b/ntoskrnl/kdbg/kdb.h @@ -98,10 +98,15 @@ KdbpCliMainLoop( VOID KdbpCliInterpretInitFile(VOID);
+VOID +KdbpPager( + _In_ PCHAR Buffer, + _In_ ULONG BufLength); + VOID KdbpPrint( - IN PCHAR Format, - IN ... OPTIONAL); + _In_ PSTR Format, + _In_ ...);
VOID KdbpPrintUnicodeString( diff --git a/ntoskrnl/kdbg/kdb_cli.c b/ntoskrnl/kdbg/kdb_cli.c index e044572691d..806ace30fb2 100644 --- a/ntoskrnl/kdbg/kdb_cli.c +++ b/ntoskrnl/kdbg/kdb_cli.c @@ -2526,12 +2526,6 @@ KdbpCmdReboot( return FALSE; }
- -VOID -KdbpPager( - IN PCHAR Buffer, - IN ULONG BufLength); - /*!\brief Display debug messages on screen, with paging. * * Keys for per-page view: Home, End, PageUp, Arrow Up, PageDown, @@ -2787,266 +2781,9 @@ KdbpCmdHelp( return TRUE; }
-/*!\brief Prints the given string with printf-like formatting. - * - * \param Format Format of the string/arguments. - * \param ... Variable number of arguments matching the format specified in \a Format. - * - * \note Doesn't correctly handle \t and terminal escape sequences when calculating the - * number of lines required to print a single line from the Buffer in the terminal. - * Prints maximum 4096 chars, because of its buffer size. - * Uses KdpDPrintf internally (NOT DbgPrint!). Callers must already hold the debugger lock. - */ -VOID -KdbpPrint( - IN PCHAR Format, - IN ... OPTIONAL) -{ - static CHAR Buffer[4096]; - static BOOLEAN TerminalInitialized = FALSE; - static BOOLEAN TerminalConnected = FALSE; - static BOOLEAN TerminalReportsSize = TRUE; - CHAR c = '\0'; - PCHAR p, p2; - ULONG Length; - SIZE_T i, j; - LONG RowsPrintedByTerminal; - ULONG ScanCode; - va_list ap; - - /* Check if the user has aborted output of the current command */ - if (KdbOutputAborted) - return; - - /* Initialize the terminal */ - if (!TerminalInitialized) - { - KdpDprintf("\x1b[7h"); /* Enable linewrap */ - - /* Query terminal type */ - /*DbgPrint("\x1b[Z");*/ - KdpDprintf("\x05"); - - TerminalInitialized = TRUE; - Length = 0; - KeStallExecutionProcessor(100000); - - for (;;) - { - c = KdbpTryGetCharSerial(5000); - if (c == -1) - break; - - Buffer[Length++] = c; - if (Length >= (sizeof(Buffer) - 1)) - break; - } - - Buffer[Length] = '\0'; - if (Length > 0) - TerminalConnected = TRUE; - } - - /* Get number of rows and columns in terminal */ - if ((KdbNumberOfRowsTerminal < 0) || (KdbNumberOfColsTerminal < 0) || - (KdbNumberOfRowsPrinted) == 0) /* Refresh terminal size each time when number of rows printed is 0 */ - { - if ((KdbDebugState & KD_DEBUG_KDSERIAL) && TerminalConnected && TerminalReportsSize) - { - /* Try to query number of rows from terminal. A reply looks like "\x1b[8;24;80t" */ - TerminalReportsSize = FALSE; - KeStallExecutionProcessor(100000); - KdpDprintf("\x1b[18t"); - c = KdbpTryGetCharSerial(5000); - - if (c == KEY_ESC) - { - c = KdbpTryGetCharSerial(5000); - if (c == '[') - { - Length = 0; - - for (;;) - { - c = KdbpTryGetCharSerial(5000); - if (c == -1) - break; - - Buffer[Length++] = c; - if (isalpha(c) || Length >= (sizeof(Buffer) - 1)) - break; - } - - Buffer[Length] = '\0'; - if (Buffer[0] == '8' && Buffer[1] == ';') - { - for (i = 2; (i < Length) && (Buffer[i] != ';'); i++); - - if (Buffer[i] == ';') - { - Buffer[i++] = '\0'; - - /* Number of rows is now at Buffer + 2 and number of cols at Buffer + i */ - KdbNumberOfRowsTerminal = strtoul(Buffer + 2, NULL, 0); - KdbNumberOfColsTerminal = strtoul(Buffer + i, NULL, 0); - TerminalReportsSize = TRUE; - } - } - } - /* Clear further characters */ - while ((c = KdbpTryGetCharSerial(5000)) != -1); - } - } - - if (KdbNumberOfRowsTerminal <= 0) - { - /* Set number of rows to the default. */ - KdbNumberOfRowsTerminal = 23; //24; //Mna.: 23 for SCREEN debugport - } - else if (KdbNumberOfColsTerminal <= 0) - { - /* Set number of cols to the default. */ - KdbNumberOfColsTerminal = 75; //80; //Mna.: 75 for SCREEN debugport - } - } - - /* Get the string */ - va_start(ap, Format); - Length = _vsnprintf(Buffer, sizeof(Buffer) - 1, Format, ap); - Buffer[Length] = '\0'; - va_end(ap); - - p = Buffer; - while (p[0] != '\0') - { - i = strcspn(p, "\n"); - - /* Calculate the number of lines which will be printed in the terminal - * when outputting the current line - */ - if (i > 0) - RowsPrintedByTerminal = (i + KdbNumberOfColsPrinted - 1) / KdbNumberOfColsTerminal; - else - RowsPrintedByTerminal = 0; - - if (p[i] == '\n') - RowsPrintedByTerminal++; - - /*DbgPrint("!%d!%d!%d!%d!", KdbNumberOfRowsPrinted, KdbNumberOfColsPrinted, i, RowsPrintedByTerminal);*/ - - /* Display a prompt if we printed one screen full of text */ - if (KdbNumberOfRowsTerminal > 0 && - (LONG)(KdbNumberOfRowsPrinted + RowsPrintedByTerminal) >= KdbNumberOfRowsTerminal) - { - KdbRepeatLastCommand = FALSE; - - if (KdbNumberOfColsPrinted > 0) - KdpDprintf("\n"); - - KdpDprintf("--- Press q to abort, any other key to continue ---"); - RowsPrintedByTerminal++; /* added by Mna. */ - - if (KdbDebugState & KD_DEBUG_KDSERIAL) - c = KdbpGetCharSerial(); - else - c = KdbpGetCharKeyboard(&ScanCode); - - if (c == '\r') - { - /* Try to read '\n' which might follow '\r' - if \n is not received here - * it will be interpreted as "return" when the next command should be read. - */ - if (KdbDebugState & KD_DEBUG_KDSERIAL) - c = KdbpTryGetCharSerial(5); - else - c = KdbpTryGetCharKeyboard(&ScanCode, 5); - } - - KdpDprintf("\n"); - if (c == 'q') - { - KdbOutputAborted = TRUE; - return; - } - - KdbNumberOfRowsPrinted = 0; - KdbNumberOfColsPrinted = 0; - } - - /* Insert a NUL after the line and print only the current line. */ - if (p[i] == '\n' && p[i + 1] != '\0') - { - c = p[i + 1]; - p[i + 1] = '\0'; - } - else - { - c = '\0'; - } - - /* Remove escape sequences from the line if there's no terminal connected */ - if (!TerminalConnected) - { - while ((p2 = strrchr(p, '\x1b'))) /* Look for escape character */ - { - size_t len = strlen(p2); - if (p2[1] == '[') - { - j = 2; - while (!isalpha(p2[j++])); - memmove(p2, p2 + j, len + 1 - j); - } - else - { - memmove(p2, p2 + 1, len); - } - } - } - - KdpDprintf("%s", p); - - if (c != '\0') - p[i + 1] = c; - - /* Set p to the start of the next line and - * remember the number of rows/cols printed - */ - p += i; - if (p[0] == '\n') - { - p++; - KdbNumberOfColsPrinted = 0; - } - else - { - ASSERT(p[0] == '\0'); - KdbNumberOfColsPrinted += i; - } - - KdbNumberOfRowsPrinted += RowsPrintedByTerminal; - } -} - -VOID -KdbpPrintUnicodeString( - _In_ PCUNICODE_STRING String) -{ - ULONG i; - - if ((String == NULL) || (String->Buffer == NULL)) - { - KdbpPrint("<NULL>"); - return; - } - - for (i = 0; i < String->Length / sizeof(WCHAR); i++) - { - KdbpPrint("%c", (CHAR)String->Buffer[i]); - } -}
-/** memrchr(), explicitly defined, since was absent in MinGW of RosBE. */ /* + * memrchr(), explicitly defined, since absent in the CRT. * Reverse memchr() * Find the last occurrence of 'c' in the buffer 's' of size 'n'. */ @@ -3078,14 +2815,17 @@ memrchr(const void *s, int c, size_t n) * Used by KdbpPager(). * Now N lines count is hardcoded to KdbNumberOfRowsTerminal. */ -PCHAR -CountOnePageUp(PCHAR Buffer, ULONG BufLength, PCHAR pCurPos) +static PCHAR +CountOnePageUp( + _In_ PCCH Buffer, + _In_ ULONG BufLength, + _In_ PCCH pCurPos) { - PCHAR p; + PCCH p; // p0 is initial guess of Page Start ULONG p0len = KdbNumberOfRowsTerminal * KdbNumberOfColsTerminal; - PCHAR p0 = pCurPos - p0len; - PCHAR prev_p = p0, p1; + PCCH p0 = pCurPos - p0len; + PCCH prev_p = p0, p1; ULONG j;
if (pCurPos < Buffer) @@ -3093,7 +2833,7 @@ CountOnePageUp(PCHAR Buffer, ULONG BufLength, PCHAR pCurPos) ASSERT(pCurPos <= Buffer + BufLength);
p = memrchr(p0, '\n', p0len); - if (NULL == p) + if (!p) p = p0; for (j = KdbNumberOfRowsTerminal; j--; ) { @@ -3101,10 +2841,10 @@ CountOnePageUp(PCHAR Buffer, ULONG BufLength, PCHAR pCurPos) p1 = memrchr(p0, '\n', p-p0); prev_p = p; p = p1; - if (NULL == p) + if (!p) { p = prev_p; - if (NULL == p) + if (!p) p = p0; break; } @@ -3113,9 +2853,33 @@ CountOnePageUp(PCHAR Buffer, ULONG BufLength, PCHAR pCurPos) j -= linesCnt-1; }
- ASSERT(p != 0); + ASSERT(p != NULL); ++p; - return p; + return (PCHAR)p; +} + +static VOID +KdpFilterEscapes( + _Inout_ PSTR String) +{ + PCHAR p; + SIZE_T i; + size_t len; + + while ((p = strrchr(String, '\x1b'))) /* Look for escape character */ + { + len = strlen(p); + if (p[1] == '[') + { + i = 2; + while (!isalpha(p[i++])); + memmove(p, p + i, len + 1 - i); + } + else + { + memmove(p, p + 1, len); + } + } }
/*!\brief Prints the given string with, page by page. @@ -3126,27 +2890,28 @@ CountOnePageUp(PCHAR Buffer, ULONG BufLength, PCHAR pCurPos) * \note Doesn't correctly handle \t and terminal escape sequences when calculating the * number of lines required to print a single line from the Buffer in the terminal. * Maximum length of buffer is limited only by memory size. + * Uses KdpDprintf internally (NOT DbgPrint!). Callers must already hold the debugger lock. * * Note: BufLength should be greater then (KdbNumberOfRowsTerminal * KdbNumberOfColsTerminal). - * */ VOID -KdbpPager( - IN PCHAR Buffer, - IN ULONG BufLength) +KdbpPagerInternal( + _In_ PCHAR Buffer, + _In_ ULONG BufLength, + _In_ BOOLEAN DoPage) { - static CHAR InBuffer[4096]; + static CHAR InBuffer[128]; static BOOLEAN TerminalInitialized = FALSE; static BOOLEAN TerminalConnected = FALSE; static BOOLEAN TerminalReportsSize = TRUE; - CHAR c = '\0'; - PCHAR p, p2; + CHAR c; + ULONG ScanCode; + PCHAR p; ULONG Length; - SIZE_T i, j; + SIZE_T i; LONG RowsPrintedByTerminal; - ULONG ScanCode;
- if( BufLength == 0) + if (BufLength == 0) return;
/* Check if the user has aborted output of the current command */ @@ -3156,13 +2921,14 @@ KdbpPager( /* Initialize the terminal */ if (!TerminalInitialized) { + TerminalInitialized = TRUE; + KdpDprintf("\x1b[7h"); /* Enable linewrap */
/* Query terminal type */ /*DbgPrint("\x1b[Z");*/ KdpDprintf("\x05");
- TerminalInitialized = TRUE; Length = 0; KeStallExecutionProcessor(100000);
@@ -3184,7 +2950,8 @@ KdbpPager(
/* Get number of rows and columns in terminal */ if ((KdbNumberOfRowsTerminal < 0) || (KdbNumberOfColsTerminal < 0) || - (KdbNumberOfRowsPrinted) == 0) /* Refresh terminal size each time when number of rows printed is 0 */ + /* Refresh terminal size each time when number of rows printed is 0 */ + (KdbNumberOfRowsPrinted) == 0) { if ((KdbDebugState & KD_DEBUG_KDSERIAL) && TerminalConnected && TerminalReportsSize) { @@ -3235,36 +3002,45 @@ KdbpPager(
if (KdbNumberOfRowsTerminal <= 0) { - /* Set number of rows to the default. */ - KdbNumberOfRowsTerminal = 24; + /* Set number of rows to the default */ + if (!DoPage) + KdbNumberOfRowsTerminal = 23; //Mna.: for SCREEN debugport + else + KdbNumberOfRowsTerminal = 24; } else if (KdbNumberOfColsTerminal <= 0) { - /* Set number of cols to the default. */ - KdbNumberOfColsTerminal = 80; + /* Set number of cols to the default */ + if (!DoPage) + KdbNumberOfColsTerminal = 75; //Mna.: for SCREEN debugport + else + KdbNumberOfColsTerminal = 80; } }
- /* Get the string */ + /* Loop through the strings */ p = Buffer; - while (p[0] != '\0') { - if ( p > Buffer+BufLength) + if (DoPage) { - KdpDprintf("Dmesg: error, p > Buffer+BufLength,d=%d", p - (Buffer+BufLength)); - return; + if (p > Buffer + BufLength) + { + KdpDprintf("Dmesg: error, p > Buffer+BufLength,d=%d", p - (Buffer + BufLength)); + return; + } } i = strcspn(p, "\n");
- // Are we out of buffer? - if (p + i > Buffer + BufLength) - // Leaving pager function: - break; + if (DoPage) + { + /* Are we out of buffer? */ + if (p + i > Buffer + BufLength) + break; // Leaving pager function + }
- /* Calculate the number of lines which will be printed in the terminal - * when outputting the current line. - */ + /* Calculate the number of lines which will be printed in + * the terminal when outputting the current line. */ if (i > 0) RowsPrintedByTerminal = (i + KdbNumberOfColsPrinted - 1) / KdbNumberOfColsTerminal; else @@ -3273,7 +3049,7 @@ KdbpPager( if (p[i] == '\n') RowsPrintedByTerminal++;
- /*DbgPrint("!%d!%d!%d!%d!", KdbNumberOfRowsPrinted, KdbNumberOfColsPrinted, i, RowsPrintedByTerminal);*/ + //KdpDprintf("!%d!%d!%d!%d!", KdbNumberOfRowsPrinted, KdbNumberOfColsPrinted, i, RowsPrintedByTerminal);
/* Display a prompt if we printed one screen full of text */ if (KdbNumberOfRowsTerminal > 0 && @@ -3284,7 +3060,14 @@ KdbpPager( if (KdbNumberOfColsPrinted > 0) KdpDprintf("\n");
- KdpDprintf("--- Press q to abort, e/End,h/Home,u/PgUp, other key/PgDn ---"); + if (DoPage) + { + KdpDprintf("--- Press q to abort, e/End,h/Home,u/PgUp, other key/PgDn ---"); + } + else + { + KdpDprintf("--- Press q to abort, any other key to continue ---"); + } RowsPrintedByTerminal++;
if (KdbDebugState & KD_DEBUG_KDSERIAL) @@ -3303,41 +3086,52 @@ KdbpPager( c = KdbpTryGetCharKeyboard(&ScanCode, 5); }
- //DbgPrint("\n"); //Consize version: don't show pressed key - KdpDprintf(" '%c'/scan=%04x\n", c, ScanCode); // Shows pressed key - - if (c == 'q') - { - KdbOutputAborted = TRUE; - return; - } - if ( ScanCode == KEYSC_END || c=='e') + if (DoPage) { - PCHAR pBufEnd = Buffer + BufLength; - p = CountOnePageUp(Buffer, BufLength, pBufEnd); - i = strcspn(p, "\n"); + //KdpDprintf("\n"); // Concise version: don't show pressed key + KdpDprintf(" '%c'/scan=%04x\n", c, ScanCode); // Shows pressed key } - else if (ScanCode == KEYSC_PAGEUP || c=='u') + else { - p = CountOnePageUp(Buffer, BufLength, p); - i = strcspn(p, "\n"); + KdpDprintf("\n"); } - else if (ScanCode == KEYSC_HOME || c=='h') + + if (c == 'q') { - p = Buffer; - i = strcspn(p, "\n"); + KdbOutputAborted = TRUE; + return; } - else if (ScanCode == KEYSC_ARROWUP) + + if (DoPage) { - p = CountOnePageUp(Buffer, BufLength, p); - i = strcspn(p, "\n"); + if (ScanCode == KEYSC_END || c == 'e') + { + PCHAR pBufEnd = Buffer + BufLength; + p = CountOnePageUp(Buffer, BufLength, pBufEnd); + i = strcspn(p, "\n"); + } + else if (ScanCode == KEYSC_PAGEUP || c == 'u') + { + p = CountOnePageUp(Buffer, BufLength, p); + i = strcspn(p, "\n"); + } + else if (ScanCode == KEYSC_HOME || c == 'h') + { + p = Buffer; + i = strcspn(p, "\n"); + } + else if (ScanCode == KEYSC_ARROWUP) + { + p = CountOnePageUp(Buffer, BufLength, p); + i = strcspn(p, "\n"); + } }
KdbNumberOfRowsPrinted = 0; KdbNumberOfColsPrinted = 0; }
- /* Insert a NUL after the line and print only the current line. */ + /* Insert a NUL after the line and print only the current line */ if (p[i] == '\n' && p[i + 1] != '\0') { c = p[i + 1]; @@ -3348,35 +3142,21 @@ KdbpPager( c = '\0'; }
- /* Remove escape sequences from the line if there's no terminal connected */ + /* Remove escape sequences from the line if there is no terminal connected */ + // FIXME: Dangerous operation since we modify the source string!! if (!TerminalConnected) - { - while ((p2 = strrchr(p, '\x1b'))) /* Look for escape character */ - { - size_t len = strlen(p2); - if (p2[1] == '[') - { - j = 2; - while (!isalpha(p2[j++])); - memmove(p2, p2 + j, len + 1 - j); - } - else - { - memmove(p2, p2 + 1, len); - } - } - } + KdpFilterEscapes(p);
- // The main printing of the current line: - KdpDprintf(p); + /* Print the current line */ + // KdpDprintf(p); + KdpDprintf("%s", p);
- // restore not null char with saved: + /* Restore not null char with saved */ if (c != '\0') p[i + 1] = c;
/* Set p to the start of the next line and - * remember the number of rows/cols printed - */ + * remember the number of rows/cols printed */ p += i; if (p[0] == '\n') { @@ -3393,6 +3173,78 @@ KdbpPager( } }
+/*!\brief Prints the given string with, page by page. + * + * \param Buffer Characters buffer to print. + * \param BufferLen Buffer size. + * + * \note Doesn't correctly handle \t and terminal escape sequences when calculating the + * number of lines required to print a single line from the Buffer in the terminal. + * Maximum length of buffer is limited only by memory size. + * Uses KdpDprintf internally (NOT DbgPrint!). Callers must already hold the debugger lock. + * + * Note: BufLength should be greater then (KdbNumberOfRowsTerminal * KdbNumberOfColsTerminal). + */ +VOID +KdbpPager( + _In_ PCHAR Buffer, + _In_ ULONG BufLength) +{ + /* Call the internal function */ + KdbpPagerInternal(Buffer, BufLength, TRUE); +} + +/*!\brief Prints the given string with printf-like formatting. + * + * \param Format Format of the string/arguments. + * \param ... Variable number of arguments matching the format specified in \a Format. + * + * \note Doesn't correctly handle \t and terminal escape sequences when calculating the + * number of lines required to print a single line from the Buffer in the terminal. + * Prints maximum 4096 chars, because of its buffer size. + */ +VOID +KdbpPrint( + _In_ PSTR Format, + _In_ ...) +{ + static CHAR Buffer[4096]; + ULONG Length; + va_list ap; + + /* Check if the user has aborted output of the current command */ + if (KdbOutputAborted) + return; + + /* Build the string */ + va_start(ap, Format); + Length = _vsnprintf(Buffer, sizeof(Buffer) - 1, Format, ap); + Buffer[Length] = '\0'; + va_end(ap); + + /* Actually print it */ + KdbpPagerInternal(Buffer, Length, FALSE); +} + +VOID +KdbpPrintUnicodeString( + _In_ PCUNICODE_STRING String) +{ + ULONG i; + + if ((String == NULL) || (String->Buffer == NULL)) + { + KdbpPrint("<NULL>"); + return; + } + + for (i = 0; i < String->Length / sizeof(WCHAR); i++) + { + KdbpPrint("%c", (CHAR)String->Buffer[i]); + } +} + + /*!\brief Appends a command to the command history * * \param Command Pointer to the command to append to the history.