diff --git a/reactos/lib/sdk/crt/conio/kbhit.c b/reactos/lib/sdk/crt/conio/kbhit.c index 60e3e06d8c0..0f29390d82a 100644 --- a/reactos/lib/sdk/crt/conio/kbhit.c +++ b/reactos/lib/sdk/crt/conio/kbhit.c @@ -3,28 +3,99 @@ * PROJECT: ReactOS system libraries * FILE: lib/msvcrt/conio/kbhit.c * PURPOSE: Checks for keyboard hits - * PROGRAMER: Ariadne + * PROGRAMERS: Ariadne, Russell * UPDATE HISTORY: * 28/12/98: Created + * 27/9/08: An almost 100% working version of _kbhit() */ #include +static CRITICAL_SECTION CriticalSection; +volatile BOOL CriticalSectionInitialized=FALSE; + /* - * FIXME PeekConsoleInput returns more than keyboard hits + * FIXME Initial keyboard char not detected on first punch * - * @unimplemented + * @implemented */ + int _kbhit(void) { - //INPUT_RECORD InputRecord; - DWORD NumberRead=0; - if (char_avail) - return(1); - else { - //FIXME PeekConsoleInput might do DeviceIo - //PeekConsoleInput((HANDLE)stdin->_file,&InputRecord,1,&NumberRead); - return NumberRead; + PINPUT_RECORD InputRecord = NULL; + DWORD NumberRead = 0; + DWORD EventsRead = 0; + DWORD RecordIndex = 0; + DWORD BufferIndex = 0; + HANDLE StdInputHandle = 0; + DWORD ConsoleInputMode = 0; + + /* Attempt some thread safety */ + if (!CriticalSectionInitialized) + { + InitializeCriticalSectionAndSpinCount(&CriticalSection, 0x80000400); + CriticalSectionInitialized = TRUE; } - return 0; + + EnterCriticalSection(&CriticalSection); + + if (char_avail) + { + LeaveCriticalSection(&CriticalSection); + return 1; + } + + StdInputHandle = GetStdHandle(STD_INPUT_HANDLE); + + /* Turn off processed input so we get key modifiers as well */ + GetConsoleMode(StdInputHandle, &ConsoleInputMode); + + SetConsoleMode(StdInputHandle, ConsoleInputMode & ~ENABLE_PROCESSED_INPUT); + + /* Start the process */ + if (!GetNumberOfConsoleInputEvents(StdInputHandle, &EventsRead)) + { + LeaveCriticalSection(&CriticalSection); + return 0; + } + + if (!EventsRead) + { + LeaveCriticalSection(&CriticalSection); + return 0; + } + + if (!(InputRecord = (PINPUT_RECORD)malloc(EventsRead * sizeof(INPUT_RECORD)))) + { + LeaveCriticalSection(&CriticalSection); + return 0; + } + + if (!ReadConsoleInput(StdInputHandle, InputRecord, EventsRead, &NumberRead)) + { + free(InputRecord); + LeaveCriticalSection(&CriticalSection); + return 0; + } + + for (RecordIndex = 0; RecordIndex < NumberRead; RecordIndex++) + { + if (InputRecord[RecordIndex].EventType == KEY_EVENT && + InputRecord[RecordIndex].Event.KeyEvent.bKeyDown) + { + BufferIndex = 1; + break; + } + } + + free(InputRecord); + + /* Restore console input mode */ + SetConsoleMode(StdInputHandle, ConsoleInputMode); + + LeaveCriticalSection(&CriticalSection); + + return BufferIndex; } + +