From acfe187655c4823cdc3588bc9e2c8899ceb57253 Mon Sep 17 00:00:00 2001 From: Aleksandar Andrejevic Date: Sat, 26 Sep 2015 00:05:10 +0000 Subject: [PATCH] [NTVDM] Fix INT 21h/0Ah. DosReadCharacter shouldn't echo all the time. svn path=/trunk/; revision=69359 --- .../mvdm/ntvdm/dos/dos32krnl/bios.c | 14 +- .../subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c | 19 +- .../subsystems/mvdm/ntvdm/dos/dos32krnl/dos.h | 2 +- .../mvdm/ntvdm/dos/dos32krnl/dosfiles.c | 164 ++++++++++-------- .../mvdm/ntvdm/dos/dos32krnl/dosfiles.h | 1 + 5 files changed, 104 insertions(+), 96 deletions(-) diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/bios.c b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/bios.c index 0a8d02db2a5..fe3394715bd 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/bios.c +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/bios.c @@ -79,16 +79,14 @@ VOID DosEchoCharacter(CHAR Character) DosPrintCharacter(DOS_OUTPUT_HANDLE, '^'); Character += 'A' - 1; } - else - { - /* Echo the character */ - DosPrintCharacter(DOS_OUTPUT_HANDLE, Character); - } + + /* Echo the character */ + DosPrintCharacter(DOS_OUTPUT_HANDLE, Character); } } } -CHAR DosReadCharacter(WORD FileHandle) +CHAR DosReadCharacter(WORD FileHandle, BOOLEAN Echo) { WORD BytesRead; PDOS_FILE_DESCRIPTOR Descriptor = NULL; @@ -111,8 +109,8 @@ CHAR DosReadCharacter(WORD FileHandle) 1, &BytesRead); - /* Check if the file is actually the CON device */ - if (Descriptor && Descriptor->DeviceInfo & FILE_INFO_DEVICE) + /* Check if we should echo and the file is actually the CON device */ + if (Echo && Descriptor && Descriptor->DeviceInfo & FILE_INFO_DEVICE) { /* Echo the character */ DosEchoCharacter(Sda->ByteBuffer); diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c index 0414a060fd3..1e42602cbca 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c @@ -214,7 +214,7 @@ VOID WINAPI DosInt21h(LPWORD Stack) { DPRINT("INT 21h, AH = 01h\n"); - Character = DosReadCharacter(DOS_INPUT_HANDLE); + Character = DosReadCharacter(DOS_INPUT_HANDLE, TRUE); if (Character == 0x03 && DosControlBreak()) break; setAL(Character); @@ -292,7 +292,7 @@ VOID WINAPI DosInt21h(LPWORD Stack) if (DosCheckInput()) { Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_ZF; - setAL(DosReadCharacter(DOS_INPUT_HANDLE)); + setAL(DosReadCharacter(DOS_INPUT_HANDLE, FALSE)); } else { @@ -309,7 +309,7 @@ VOID WINAPI DosInt21h(LPWORD Stack) case 0x07: { DPRINT("Direct char input without echo\n"); - setAL(DosReadCharacter(DOS_INPUT_HANDLE)); + setAL(DosReadCharacter(DOS_INPUT_HANDLE, FALSE)); break; } @@ -318,7 +318,7 @@ VOID WINAPI DosInt21h(LPWORD Stack) { DPRINT("Char input without echo\n"); - Character = DosReadCharacter(DOS_INPUT_HANDLE); + Character = DosReadCharacter(DOS_INPUT_HANDLE, FALSE); if (Character == 0x03 && DosControlBreak()) break; setAL(Character); @@ -348,19 +348,18 @@ VOID WINAPI DosInt21h(LPWORD Stack) /* Read Buffered Input */ case 0x0A: { - WORD BytesRead; PDOS_INPUT_BUFFER InputBuffer = (PDOS_INPUT_BUFFER)SEG_OFF_TO_PTR(getDS(), getDX()); DPRINT("Read Buffered Input\n"); if (InputBuffer->MaxLength == 0) break; /* Read from standard input */ - DosReadFile(DOS_INPUT_HANDLE, - MAKELONG(getDX() + FIELD_OFFSET(DOS_INPUT_BUFFER, Buffer), getDS()), - InputBuffer->MaxLength, - &BytesRead); + InputBuffer->Length = DosReadLineBuffered( + DOS_INPUT_HANDLE, + MAKELONG(getDX() + FIELD_OFFSET(DOS_INPUT_BUFFER, Buffer), getDS()), + InputBuffer->MaxLength + ); - InputBuffer->Length = LOBYTE(BytesRead); break; } diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.h b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.h index f8db858fa17..18e50077d4a 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.h +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.h @@ -318,7 +318,7 @@ VOID ConDrvCleanup(VOID); * DOS BIOS Functions * See bios.c */ -CHAR DosReadCharacter(WORD FileHandle); +CHAR DosReadCharacter(WORD FileHandle, BOOLEAN Echo); BOOLEAN DosCheckInput(VOID); VOID DosPrintCharacter(WORD FileHandle, CHAR Character); diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dosfiles.c b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dosfiles.c index e792239fd1d..ad710c4386f 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dosfiles.c +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dosfiles.c @@ -669,6 +669,90 @@ WORD DosOpenFile(LPWORD Handle, return ERROR_SUCCESS; } +BYTE DosReadLineBuffered(WORD FileHandle, DWORD Buffer, BYTE MaxSize) +{ + PDOS_FILE_DESCRIPTOR Descriptor = DosGetHandleFileDescriptor(FileHandle); + PDOS_DEVICE_NODE Node = DosGetDriverNode(Descriptor->DevicePointer); + BYTE LineSize = 0; + PCHAR Pointer = FAR_POINTER(Buffer); + + while (TRUE) + { + USHORT Amount = 1; + CHAR Character; + + /* Read a character from the device */ + Node->ReadRoutine(Node, + MAKELONG(DOS_DATA_OFFSET(Sda.ByteBuffer), + DOS_DATA_SEGMENT), + &Amount); + if (Amount == 0) break; + + Character = Sda->ByteBuffer; + + if (LineSize == MaxSize - 1 && Character != '\r' && Character != '\b') + { + /* Line buffer full */ + // TODO: Should we beep? + continue; + } + + switch (Character) + { + /* Extended character */ + case '\0': + { + /* Read the scancode and discard it */ + Amount = 1; + Node->ReadRoutine(Node, + MAKELONG(DOS_DATA_OFFSET(Sda.ByteBuffer), + DOS_DATA_SEGMENT), + &Amount); + break; + } + + /* Ctrl-C */ + case 0x03: + { + DosEchoCharacter(Character); + + if (DosControlBreak()) + { + /* Set the character to CR to end the loop */ + Character = '\r'; + } + + break; + } + + case '\b': + { + if (LineSize > 0) + { + LineSize--; + if (Pointer[LineSize] == 0) LineSize--; + + DosEchoCharacter(Character); + } + + break; + } + + default: + { + /* Store the character in the buffer */ + Pointer[LineSize++] = Character; + DosEchoCharacter(Character); + } + } + + /* Stop on a carriage return */ + if (Character == '\r') break; + } + + return LineSize - 1; +} + WORD DosReadFile(WORD FileHandle, DWORD Buffer, WORD Count, @@ -706,85 +790,11 @@ WORD DosReadFile(WORD FileHandle, /* Check if the buffer is empty */ if (!SysVars->UnreadConInput) { - ULONG LineSize = 0; - SysVars->UnreadConInput = FIELD_OFFSET(DOS_DATA, UnreadConInputBuffer); - ConBuffer = (PCHAR)SEG_OFF_TO_PTR(DOS_DATA_SEGMENT, SysVars->UnreadConInput); - while (TRUE) - { - USHORT Amount = 1; - CHAR Character; - - /* Read a character from the CON device */ - Node->ReadRoutine(Node, - MAKELONG(DOS_DATA_OFFSET(Sda.ByteBuffer), - DOS_DATA_SEGMENT), - &Amount); - if (Amount == 0) break; - - Character = Sda->ByteBuffer; - - if (LineSize == sizeof(DosData->UnreadConInputBuffer)-1 && - Character != '\r' && Character != '\b') - { - /* Line buffer full */ - // TODO: Should we beep? - continue; - } - - switch (Character) - { - /* Extended character */ - case '\0': - { - /* Read the scancode and discard it */ - Amount = 1; - Node->ReadRoutine(Node, - MAKELONG(DOS_DATA_OFFSET(Sda.ByteBuffer), - DOS_DATA_SEGMENT), - &Amount); - break; - } - - /* Ctrl-C */ - case 0x03: - { - DosEchoCharacter(Character); - - if (DosControlBreak()) - { - /* Set the character to CR to end the loop */ - Character = '\r'; - } - - break; - } - - case '\b': - { - if (LineSize > 0) - { - LineSize--; - if (ConBuffer[LineSize] == 0) LineSize--; - - DosEchoCharacter(Character); - } - - break; - } - - default: - { - /* Store the character in the buffer */ - ConBuffer[LineSize++] = Character; - DosEchoCharacter(Character); - } - } - - /* Stop on a carriage return */ - if (Character == '\r') break; - } + DosReadLineBuffered(FileHandle, + MAKELONG(SysVars->UnreadConInput, DOS_DATA_SEGMENT), + sizeof(DosData->UnreadConInputBuffer)); } *BytesRead = 0; diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dosfiles.h b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dosfiles.h index 4d7a651fab6..1afc34bde32 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dosfiles.h +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dosfiles.h @@ -123,6 +123,7 @@ WORD DosSeekFile LPDWORD NewOffset ); +BYTE DosReadLineBuffered(WORD FileHandle, DWORD Buffer, BYTE MaxSize); BOOL DosFlushFileBuffers(WORD FileHandle); BOOLEAN DosLockFile(WORD DosHandle, DWORD Offset, DWORD Size); BOOLEAN DosUnlockFile(WORD DosHandle, DWORD Offset, DWORD Size);