From d5976d273951a09d2b9deca1f4b7745818fa9259 Mon Sep 17 00:00:00 2001 From: Aleksandar Andrejevic Date: Tue, 31 Mar 2015 21:28:40 +0000 Subject: [PATCH] [NTVDM] - Implement Ctrl-C using interrupt 0x23. - Fix INT 21h, AH = 0Ah to detect special characters. - When attaching to / detaching from the console, adjust the console mode and attach/detach the UI. - Do not translate scancodes to characters while ALT is held down. svn path=/trunk/; revision=67002 --- .../mvdm/ntvdm/bios/bios32/kbdbios32.c | 12 ++- .../subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c | 93 ++++++++++++++----- reactos/subsystems/mvdm/ntvdm/emulator.c | 36 ------- reactos/subsystems/mvdm/ntvdm/ntvdm.c | 50 ++++++++-- reactos/subsystems/mvdm/ntvdm/ntvdm.h | 2 + 5 files changed, 121 insertions(+), 72 deletions(-) diff --git a/reactos/subsystems/mvdm/ntvdm/bios/bios32/kbdbios32.c b/reactos/subsystems/mvdm/ntvdm/bios/bios32/kbdbios32.c index 476296a02bc..e7c4650065b 100644 --- a/reactos/subsystems/mvdm/ntvdm/bios/bios32/kbdbios32.c +++ b/reactos/subsystems/mvdm/ntvdm/bios/bios32/kbdbios32.c @@ -245,12 +245,16 @@ static VOID WINAPI BiosKeyboardIrq(LPWORD Stack) /* Set the highest bit */ BiosKeyboardMap[VirtualKey] |= (1 << 7); - /* Find out which character this is */ Character = 0; - if (ToAscii(VirtualKey, ScanCode, BiosKeyboardMap, &Character, 0) == 0) + + /* If ALT isn't held down, find out which character this is */ + if (!((BiosKeyboardMap[VK_MENU] | BiosKeyboardMap[VK_RMENU] | BiosKeyboardMap[VK_LMENU]) & (1 << 7))) { - /* Not ASCII */ - Character = 0; + if (ToAscii(VirtualKey, ScanCode, BiosKeyboardMap, &Character, 0) == 0) + { + /* Not ASCII */ + Character = 0; + } } /* Push it onto the BIOS keyboard queue */ diff --git a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c index 0a5e4eb8db7..d0c03fdca07 100644 --- a/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c +++ b/reactos/subsystems/mvdm/ntvdm/dos/dos32krnl/dos.c @@ -650,6 +650,22 @@ static BOOLEAN DosChangeDirectory(LPSTR Directory) return TRUE; } +static BOOLEAN DosControlBreak(VOID) +{ + setCF(0); + + /* Call interrupt 0x23 */ + Int32Call(&DosContext, 0x23); + + if (getCF()) + { + DosTerminateProcess(CurrentPsp, 0, 0); + return TRUE; + } + + return FALSE; +} + /* PUBLIC FUNCTIONS ***********************************************************/ PDOS_SFT_ENTRY DosGetSftEntry(WORD DosHandle) @@ -981,7 +997,8 @@ DWORD DosStartProcess(IN LPCSTR ExecutablePath, if (Result != ERROR_SUCCESS) goto Quit; /* Attach to the console */ - VidBiosAttachToConsole(); // FIXME: And in fact, attach the full NTVDM UI to the console + ConsoleAttach(); + VidBiosAttachToConsole(); // HACK: Simulate a ENTER key release scancode on the PS/2 port because // some apps expect to read a key release scancode (> 0x80) when they @@ -994,7 +1011,8 @@ DWORD DosStartProcess(IN LPCSTR ExecutablePath, CpuSimulate(); /* Detach from the console */ - VidBiosDetachFromConsole(); // FIXME: And in fact, detach the full NTVDM UI from the console + VidBiosDetachFromConsole(); + ConsoleDetach(); Quit: return Result; @@ -1125,9 +1143,10 @@ VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode, WORD KeepResident) LPDWORD IntVecTable = (LPDWORD)((ULONG_PTR)BaseAddress); PDOS_PSP PspBlock = SEGMENT_TO_PSP(Psp); - DPRINT("DosTerminateProcess: Psp 0x%04X, ReturnCode 0x%02X\n", + DPRINT("DosTerminateProcess: Psp 0x%04X, ReturnCode 0x%02X, KeepResident 0x%04X\n", Psp, - ReturnCode); + ReturnCode, + KeepResident); /* Check if this PSP is it's own parent */ if (PspBlock->ParentPsp == Psp) goto Done; @@ -1464,16 +1483,12 @@ VOID WINAPI DosInt21h(LPWORD Stack) { DPRINT("Char input without echo\n"); - // FIXME: Under DOS 2+, input handle may be redirected!!!! Character = DosReadCharacter(DOS_INPUT_HANDLE); // FIXME: For 0x07, do not check Ctrl-C/Break. // For 0x08, do check those control sequences and if needed, // call INT 0x23. - // /* Let the BOP repeat if needed */ - // if (getCF()) break; - setAL(Character); break; } @@ -1508,18 +1523,55 @@ VOID WINAPI DosInt21h(LPWORD Stack) while (Count < InputBuffer->MaxLength) { - // FIXME!! This function should interpret backspaces etc... - /* Try to read a character (wait) */ Character = DosReadCharacter(DOS_INPUT_HANDLE); - // FIXME: Check whether Ctrl-C / Ctrl-Break is pressed, and call INT 23h if so. - - /* Echo the character and append it to the buffer */ - DosPrintCharacter(DOS_OUTPUT_HANDLE, Character); - InputBuffer->Buffer[Count] = Character; - - Count++; /* Carriage returns are also counted */ + switch (Character) + { + /* Extended character */ + case '\0': + { + /* Read the scancode */ + DosReadCharacter(DOS_INPUT_HANDLE); + break; + } + + /* Ctrl-C */ + case 0x03: + { + if (DosControlBreak()) return; + break; + } + + /* Backspace */ + case '\b': + { + if (Count > 0) + { + Count--; + + /* Erase the character */ + DosPrintCharacter(DOS_OUTPUT_HANDLE, '\b'); + DosPrintCharacter(DOS_OUTPUT_HANDLE, ' '); + DosPrintCharacter(DOS_OUTPUT_HANDLE, '\b'); + } + + break; + } + + default: + { + if (Character == 0x0A || Character == 0x0D + || (Character >= 0x20 && Character <= 0x7F)) + { + /* Echo the character and append it to the buffer */ + DosPrintCharacter(DOS_OUTPUT_HANDLE, Character); + InputBuffer->Buffer[Count] = Character; + + Count++; /* Carriage returns are also counted */ + } + } + } if (Character == '\r') break; } @@ -2836,11 +2888,8 @@ VOID WINAPI DosInt21h(LPWORD Stack) VOID WINAPI DosBreakInterrupt(LPWORD Stack) { - UNREFERENCED_PARAMETER(Stack); - - /* Stop the VDM task */ - ResetEvent(VdmTaskEvent); - CpuUnsimulate(); + /* Set CF to terminate the running process */ + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; } VOID WINAPI DosFastConOut(LPWORD Stack) diff --git a/reactos/subsystems/mvdm/ntvdm/emulator.c b/reactos/subsystems/mvdm/ntvdm/emulator.c index 74bd599fb3d..2de9db12c1e 100644 --- a/reactos/subsystems/mvdm/ntvdm/emulator.c +++ b/reactos/subsystems/mvdm/ntvdm/emulator.c @@ -316,34 +316,6 @@ PumpConsoleInput(LPVOID Parameter) return 0; } -static VOID EnableExtraHardware(HANDLE ConsoleInput) -{ - DWORD ConInMode; - - if (GetConsoleMode(ConsoleInput, &ConInMode)) - { -#if 0 - // GetNumberOfConsoleMouseButtons(); - // GetSystemMetrics(SM_CMOUSEBUTTONS); - // GetSystemMetrics(SM_MOUSEPRESENT); - if (MousePresent) - { -#endif - /* Support mouse input events if there is a mouse on the system */ - ConInMode |= ENABLE_MOUSE_INPUT; -#if 0 - } - else - { - /* Do not support mouse input events if there is no mouse on the system */ - ConInMode &= ~ENABLE_MOUSE_INPUT; - } -#endif - - SetConsoleMode(ConsoleInput, ConInMode); - } -} - /* PUBLIC FUNCTIONS ***********************************************************/ static VOID @@ -498,14 +470,6 @@ BOOLEAN EmulatorInitialize(HANDLE ConsoleInput, HANDLE ConsoleOutput) /* Register the I/O Ports */ RegisterIoPort(CONTROL_SYSTEM_PORT61H, Port61hRead, Port61hWrite); - /* Set the console input mode */ - // FIXME: Activate ENABLE_WINDOW_INPUT when we will want to perform actions - // upon console window events (screen buffer resize, ...). - SetConsoleMode(ConsoleInput, ENABLE_PROCESSED_INPUT /* | ENABLE_WINDOW_INPUT */); - // SetConsoleMode(ConsoleOutput, ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT); - - /**/EnableExtraHardware(ConsoleInput);/**/ - /* Initialize the PS/2 port */ PS2Initialize(); diff --git a/reactos/subsystems/mvdm/ntvdm/ntvdm.c b/reactos/subsystems/mvdm/ntvdm/ntvdm.c index 54b868a6c6e..58f18bffb76 100644 --- a/reactos/subsystems/mvdm/ntvdm/ntvdm.c +++ b/reactos/subsystems/mvdm/ntvdm/ntvdm.c @@ -176,6 +176,34 @@ static VOID ShowHideMousePointer(HANDLE ConOutHandle, BOOLEAN ShowPtr) } } +static VOID EnableExtraHardware(HANDLE ConsoleInput) +{ + DWORD ConInMode; + + if (GetConsoleMode(ConsoleInput, &ConInMode)) + { +#if 0 + // GetNumberOfConsoleMouseButtons(); + // GetSystemMetrics(SM_CMOUSEBUTTONS); + // GetSystemMetrics(SM_MOUSEPRESENT); + if (MousePresent) + { +#endif + /* Support mouse input events if there is a mouse on the system */ + ConInMode |= ENABLE_MOUSE_INPUT; +#if 0 + } + else + { + /* Do not support mouse input events if there is no mouse on the system */ + ConInMode &= ~ENABLE_MOUSE_INPUT; + } +#endif + + SetConsoleMode(ConsoleInput, ConInMode); + } +} + /* PUBLIC FUNCTIONS ***********************************************************/ VOID @@ -232,14 +260,6 @@ ConsoleCtrlHandler(DWORD ControlType) { switch (ControlType) { - case CTRL_C_EVENT: - case CTRL_BREAK_EVENT: - { - /* HACK: Stop the VDM */ - DPRINT1("Ctrl-C/Break: Stop the VDM\n"); - EmulatorTerminate(); - break; - } case CTRL_LAST_CLOSE_EVENT: { if (WaitForSingleObject(VdmTaskEvent, 0) == WAIT_TIMEOUT) @@ -260,6 +280,7 @@ ConsoleCtrlHandler(DWORD ControlType) break; } + default: { /* Stop the VDM if the user logs out or closes the console */ @@ -284,7 +305,7 @@ ConsoleCleanupUI(VOID) DestroyVdmMenu(); } -static BOOL +BOOL ConsoleAttach(VOID) { /* Save the original input and output console modes */ @@ -297,13 +318,22 @@ ConsoleAttach(VOID) // return FALSE; } + /* Set the console input mode */ + // FIXME: Activate ENABLE_WINDOW_INPUT when we will want to perform actions + // upon console window events (screen buffer resize, ...). + SetConsoleMode(ConsoleInput, 0 /* | ENABLE_WINDOW_INPUT */); + EnableExtraHardware(ConsoleInput); + + /* Set the console output mode */ + // SetConsoleMode(ConsoleOutput, ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT); + /* Initialize the UI */ ConsoleInitUI(); return TRUE; } -static VOID +VOID ConsoleDetach(VOID) { /* Restore the original input and output console modes */ diff --git a/reactos/subsystems/mvdm/ntvdm/ntvdm.h b/reactos/subsystems/mvdm/ntvdm/ntvdm.h index ffc788470e9..7bcc748f66d 100644 --- a/reactos/subsystems/mvdm/ntvdm/ntvdm.h +++ b/reactos/subsystems/mvdm/ntvdm/ntvdm.h @@ -68,6 +68,8 @@ CreateVdmMenu(HANDLE ConOutHandle); /*static*/ VOID DestroyVdmMenu(VOID); +BOOL ConsoleAttach(VOID); +VOID ConsoleDetach(VOID); VOID MenuEventHandler(PMENU_EVENT_RECORD MenuEvent); VOID FocusEventHandler(PFOCUS_EVENT_RECORD FocusEvent); -- 2.17.1