[PATCH 1/3] [Kernel32]: when reading chars out of a bare console, use the Unix API (instead of the Windows' one).
Eric Pouech
eric.pouech at orange.fr
Sun Dec 12 15:31:32 CST 2010
A+
---
dlls/kernel32/console.c | 56 ++++++++++++++++++++++++++---------------------
1 files changed, 31 insertions(+), 25 deletions(-)
diff --git a/dlls/kernel32/console.c b/dlls/kernel32/console.c
index f3d029d..a9fd2c9 100644
--- a/dlls/kernel32/console.c
+++ b/dlls/kernel32/console.c
@@ -41,6 +41,9 @@
#ifdef HAVE_TERMIOS_H
# include <termios.h>
#endif
+#ifdef HAVE_SYS_POLL_H
+# include <sys/poll.h>
+#endif
#include "ntstatus.h"
#define WIN32_NO_STATUS
@@ -1112,33 +1115,35 @@ static BOOL handle_simple_char(HANDLE conin, unsigned real_inchar)
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;
- enum read_console_input_return ret;
- char ch;
-
- /* get the real handle to the console object */
- handle = wine_server_ptr_handle(console_handle_unmap(handle));
+ struct pollfd pollfd;
+ char ch;
+ enum read_console_input_return ret;
- memset(&ov, 0, sizeof(ov));
- ov.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
+ pollfd.fd = fd;
+ pollfd.events = POLLIN;
+ pollfd.revents = 0;
- if (ReadFile(handle, &ch, 1, NULL, &ov) ||
- (GetLastError() == ERROR_IO_PENDING &&
- WaitForSingleObject(ov.hEvent, timeout) == WAIT_OBJECT_0 &&
- GetOverlappedResult(handle, &ov, NULL, FALSE)))
+ switch (poll(&pollfd, 1, timeout))
{
- ret = handle_simple_char(handle, ch) ? rci_gotone : rci_error;
- }
- else
- {
- WARN("Failed read %x\n", GetLastError());
- ret = rci_error;
+ case 1:
+ RtlEnterCriticalSection(&CONSOLE_CritSect);
+ switch (read(fd, &ch, 1))
+ {
+ case 1: ret = handle_simple_char(handle, ch) ? rci_gotone : rci_error; break;
+ /* 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;
+ }
+ RtlLeaveCriticalSection(&CONSOLE_CritSect);
+ return ret;
+ case 0: return rci_timeout;
+ default: return rci_error;
}
- CloseHandle(ov.hEvent);
-
- return ret;
}
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)
{
put_console_into_raw_mode(fd);
- close(fd);
if (WaitForSingleObject(GetConsoleInputWaitHandle(), 0) != WAIT_OBJECT_0)
{
- ret = bare_console_fetch_input(handle, timeout);
- if (ret != rci_gotone) return ret;
+ ret = bare_console_fetch_input(handle, fd, timeout);
}
+ else ret = rci_gotone;
+ close(fd);
+ if (ret != rci_gotone) return ret;
}
else
{
More information about the wine-patches
mailing list