kernel32: When reading chars out of a bare console, use the Unix API (instead of the Windows one).

This commit is contained in:
Eric Pouech 2010-12-12 22:31:32 +01:00 committed by Alexandre Julliard
parent 10aa13a98e
commit 4149643fbe
1 changed files with 31 additions and 25 deletions

View File

@ -41,6 +41,9 @@
#ifdef HAVE_TERMIOS_H #ifdef HAVE_TERMIOS_H
# include <termios.h> # include <termios.h>
#endif #endif
#ifdef HAVE_SYS_POLL_H
# include <sys/poll.h>
#endif
#include "ntstatus.h" #include "ntstatus.h"
#define WIN32_NO_STATUS #define WIN32_NO_STATUS
@ -1112,33 +1115,35 @@ static BOOL handle_simple_char(HANDLE conin, unsigned real_inchar)
return WriteConsoleInputW(conin, ir, numEvent, &written); return WriteConsoleInputW(conin, ir, numEvent, &written);
} }
static enum read_console_input_return bare_console_fetch_input(HANDLE handle, DWORD timeout) static enum read_console_input_return bare_console_fetch_input(HANDLE handle, int fd, DWORD timeout)
{ {
OVERLAPPED ov; struct pollfd pollfd;
enum read_console_input_return ret;
char ch; char ch;
enum read_console_input_return ret;
/* get the real handle to the console object */ pollfd.fd = fd;
handle = wine_server_ptr_handle(console_handle_unmap(handle)); pollfd.events = POLLIN;
pollfd.revents = 0;
memset(&ov, 0, sizeof(ov)); switch (poll(&pollfd, 1, timeout))
ov.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
if (ReadFile(handle, &ch, 1, NULL, &ov) ||
(GetLastError() == ERROR_IO_PENDING &&
WaitForSingleObject(ov.hEvent, timeout) == WAIT_OBJECT_0 &&
GetOverlappedResult(handle, &ov, NULL, FALSE)))
{ {
ret = handle_simple_char(handle, ch) ? rci_gotone : rci_error; case 1:
} RtlEnterCriticalSection(&CONSOLE_CritSect);
else switch (read(fd, &ch, 1))
{ {
WARN("Failed read %x\n", GetLastError()); case 1: ret = handle_simple_char(handle, ch) ? rci_gotone : rci_error; break;
ret = rci_error; /* actually another thread likely beat us to reading the char
* return gotone, while not perfect, it should work in most of the cases (as the new event
* should be now in the queue)
*/
case 0: ret = rci_gotone; break;
default: ret = rci_error; break;
} }
CloseHandle(ov.hEvent); RtlLeaveCriticalSection(&CONSOLE_CritSect);
return ret; return ret;
case 0: return rci_timeout;
default: return rci_error;
}
} }
static enum read_console_input_return read_console_input(HANDLE handle, PINPUT_RECORD ir, DWORD timeout) static enum read_console_input_return read_console_input(HANDLE handle, PINPUT_RECORD ir, DWORD timeout)
@ -1149,12 +1154,13 @@ static enum read_console_input_return read_console_input(HANDLE handle, PINPUT_R
if ((fd = get_console_bare_fd(handle)) != -1) if ((fd = get_console_bare_fd(handle)) != -1)
{ {
put_console_into_raw_mode(fd); put_console_into_raw_mode(fd);
close(fd);
if (WaitForSingleObject(GetConsoleInputWaitHandle(), 0) != WAIT_OBJECT_0) if (WaitForSingleObject(GetConsoleInputWaitHandle(), 0) != WAIT_OBJECT_0)
{ {
ret = bare_console_fetch_input(handle, timeout); ret = bare_console_fetch_input(handle, fd, timeout);
if (ret != rci_gotone) return ret;
} }
else ret = rci_gotone;
close(fd);
if (ret != rci_gotone) return ret;
} }
else else
{ {