[NTOS:KDBG] Fix and improve KdbpReadCommand(). (#4914)

- Don't read anything and return immediately if the buffer size is zero.

- Allow the controlling keys (up/down arrows, backspace) even if the
  buffer is full! (especially backspace if too much has been written).

- Return the number of characters stored, not counting the NULL terminator.
This commit is contained in:
Hermès Bélusca-Maïto 2022-11-27 19:45:42 +01:00
parent 1b25fe161c
commit e619f89020
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
2 changed files with 47 additions and 34 deletions

View file

@ -3333,28 +3333,39 @@ KdbpCommandHistoryAppend(
} }
} }
/*!\brief Reads a line of user-input. /**
* @brief Reads a line of user input from the terminal.
* *
* \param Buffer Buffer to store the input into. Trailing newlines are removed. * @param[out] Buffer
* \param Size Size of \a Buffer. * Buffer where to store the input. Trailing newlines are removed.
* *
* \note Accepts only \n newlines, \r is ignored. * @param[in] Size
*/ * Size of \a Buffer.
static VOID *
* @return
* Returns the number of characters stored, not counting the NULL terminator.
*
* @note Accepts only \n newlines, \r is ignored.
**/
SIZE_T
KdbpReadCommand( KdbpReadCommand(
OUT PCHAR Buffer, _Out_ PCHAR Buffer,
IN ULONG Size) _In_ SIZE_T Size)
{ {
CHAR Key;
PCHAR Orig = Buffer; PCHAR Orig = Buffer;
ULONG ScanCode = 0; ULONG ScanCode = 0;
CHAR Key;
BOOLEAN EchoOn; BOOLEAN EchoOn;
static CHAR LastCommand[1024]; static CHAR LastCommand[1024];
static CHAR NextKey = '\0'; static CHAR NextKey = '\0';
INT CmdHistIndex = -1; INT CmdHistIndex = -1;
INT_PTR i; INT_PTR i;
EchoOn = !((KdbDebugState & KD_DEBUG_KDNOECHO) != 0); /* Bail out if the buffer is zero-sized */
if (Size == 0)
return 0;
EchoOn = ((KdbDebugState & KD_DEBUG_KDNOECHO) == 0);
for (;;) for (;;)
{ {
@ -3393,27 +3404,25 @@ KdbpReadCommand(
NextKey = '\0'; NextKey = '\0';
} }
if ((ULONG)(Buffer - Orig) >= (Size - 1)) /* Check for return or newline */
if ((Key == '\r') || (Key == '\n'))
{ {
/* Buffer is full, accept only newlines */ if (Key == '\r')
if (Key != '\n') {
continue; /*
} * We might need to discard the next '\n' which most clients
* should send after \r. Wait a bit to make sure we receive it.
*/
KeStallExecutionProcessor(100000);
if (Key == '\r') if (KdbDebugState & KD_DEBUG_KDSERIAL)
{ NextKey = KdbpTryGetCharSerial(5);
/* Read the next char - this is to throw away a \n which most clients should else
* send after \r. NextKey = KdbpTryGetCharKeyboard(&ScanCode, 5);
*/
KeStallExecutionProcessor(100000);
if (KdbDebugState & KD_DEBUG_KDSERIAL) if (NextKey == '\n' || NextKey == -1) /* \n or no response at all */
NextKey = KdbpTryGetCharSerial(5); NextKey = '\0';
else }
NextKey = KdbpTryGetCharKeyboard(&ScanCode, 5);
if (NextKey == '\n' || NextKey == -1) /* \n or no response at all */
NextKey = '\0';
KdpDprintf("\n"); KdpDprintf("\n");
@ -3432,14 +3441,14 @@ KdbpReadCommand(
else else
*Buffer = '\0'; *Buffer = '\0';
return; return (SIZE_T)(Buffer - Orig);
} }
else if (Key == KEY_BS || Key == KEY_DEL) else if (Key == KEY_BS || Key == KEY_DEL)
{ {
if (Buffer > Orig) if (Buffer > Orig)
{ {
Buffer--; Buffer--;
*Buffer = 0; *Buffer = '\0';
if (EchoOn) if (EchoOn)
KdpDprintf("%c %c", KEY_BS, KEY_BS); KdpDprintf("%c %c", KEY_BS, KEY_BS);
@ -3473,7 +3482,7 @@ KdbpReadCommand(
while (Buffer > Orig) while (Buffer > Orig)
{ {
Buffer--; Buffer--;
*Buffer = 0; *Buffer = '\0';
if (EchoOn) if (EchoOn)
KdpDprintf("%c %c", KEY_BS, KEY_BS); KdpDprintf("%c %c", KEY_BS, KEY_BS);
@ -3502,7 +3511,7 @@ KdbpReadCommand(
while (Buffer > Orig) while (Buffer > Orig)
{ {
Buffer--; Buffer--;
*Buffer = 0; *Buffer = '\0';
if (EchoOn) if (EchoOn)
KdpDprintf("%c %c", KEY_BS, KEY_BS); KdpDprintf("%c %c", KEY_BS, KEY_BS);
@ -3520,6 +3529,10 @@ KdbpReadCommand(
} }
else else
{ {
/* Don't accept any key if the buffer is full */
if ((SIZE_T)(Buffer - Orig) >= (Size - 1))
continue;
if (EchoOn) if (EchoOn)
KdpDprintf("%c", Key); KdpDprintf("%c", Key);

View file

@ -90,12 +90,12 @@ KbdSendCommandToMouse(UCHAR Command)
return; return;
} }
VOID KbdEnableMouse() VOID KbdEnableMouse(VOID)
{ {
KbdSendCommandToMouse(MOU_ENAB); KbdSendCommandToMouse(MOU_ENAB);
} }
VOID KbdDisableMouse() VOID KbdDisableMouse(VOID)
{ {
KbdSendCommandToMouse(MOU_DISAB); KbdSendCommandToMouse(MOU_DISAB);
} }