[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