[PATCH 4/5] [kernel] Support opening of console for read (try 2)

Ann and Jason Edmeades jason at edmeades.me.uk
Mon Nov 19 18:36:43 CST 2012


Try2: Fix formatting to be consistent with rest of file

Opening a bare console for read currently fails, because when a
key is pressed the kernel code needs to inject it into the keyboard
buffer which it does with WriteConsoleInput. Unfortunately this
fails as it assumes that the handle in use was opened for write.
Although reproducable with a standalone testcase, I noticed this
when trying to get cmd.exe 'copy CON filename' type support working.

This patch handles the failure only case, and retries having opened
a new handle to the console in read/write mode, hence having no
effect on the 'normal' scenario.

(Thanks to Eric for help with this one)

[Fixes 32183 and along with previous patch, fixes bug 16214]
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.winehq.org/pipermail/wine-patches/attachments/20121120/dfe39f9d/attachment.html>
-------------- next part --------------
From 13502e5c082484187c8e309525b4b96238de9185 Mon Sep 17 00:00:00 2001
From: Jason Edmeades <jason at edmeades.me.uk>
Date: Sun, 18 Nov 2012 22:32:56 +0000
Subject: [PATCH 4/5] [kernel] Support opening of console for read (try 2)

Try2: Fix formatting to be consistent with rest of file

Opening a bare console for read currently fails, because when a
key is pressed the kernel code needs to inject it into the keyboard
buffer which it does with WriteConsoleInput. Unfortunately this
fails as it assumes that the handle in use was opened for write.
Although reproducable with a standalone testcase, I noticed this
when trying to get cmd.exe 'copy CON filename' type support working.

This patch handles the failure only case, and retries having opened
a new handle to the console in read/write mode, hence having no
effect on the 'normal' scenario.

(Thanks to Eric for help with this one)

[Fixes 32183 and along with previous patch, fixes bug 16214]
---
 dlls/kernel32/console.c |   37 +++++++++++++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)

diff --git a/dlls/kernel32/console.c b/dlls/kernel32/console.c
index d6d1414..773d6df 100644
--- a/dlls/kernel32/console.c
+++ b/dlls/kernel32/console.c
@@ -1090,6 +1090,39 @@ BOOL WINAPI GetNumberOfConsoleInputEvents( HANDLE handle, LPDWORD nrofevents )
 
 
 /******************************************************************************
+ * write_console_input
+ *
+ * Helper function for bare_console_fetch_input calling WriteConsoleInput
+ * The handle passed to ReadConsole etc may not have been opened for write,
+ * and hence the calls to WriteConsoleInput may fail. This routine handles such
+ * a failure, and retries the write by opening the console for write, using
+ * it and then closing it again.
+ *
+ * Returns as per WriteConsoleInputW (TRUE on success)
+ */
+BOOL WINAPI write_console_input( HANDLE handle, const INPUT_RECORD *buffer,
+                                 DWORD count, LPDWORD written )
+{
+    BOOL result = WriteConsoleInputW(handle, buffer, count, written);
+
+    /* If this fails with access denied */
+    if (!result && GetLastError() == ERROR_ACCESS_DENIED)
+    {
+        HANDLE hConRW = CreateFileW(coninW, GENERIC_READ | GENERIC_WRITE,
+                                    FILE_SHARE_READ, NULL, OPEN_EXISTING,
+                                    FILE_ATTRIBUTE_NORMAL, 0);
+        if (hConRW != INVALID_HANDLE_VALUE)
+        {
+            result = WriteConsoleInputW(hConRW, buffer, count, written);
+            CloseHandle(hConRW);
+        }
+    }
+
+    return result;
+}
+
+
+/******************************************************************************
  * read_console_input
  *
  * Helper function for ReadConsole, ReadConsoleInput and FlushConsoleInputBuffer
@@ -1172,13 +1205,13 @@ static enum read_console_input_return bare_console_fetch_input(HANDLE handle, in
                 for (i = 0; i < idxw; i++)
                 {
                     numEvent = TERM_FillSimpleChar(inputw[i], ir);
-                    WriteConsoleInputW(handle, ir, numEvent, &written);
+                    write_console_input(handle, ir, numEvent, &written);
                 }
                 ret = rci_gotone;
                 break;
             default:
                 /* we got a transformation from key-db... push this into server */
-                ret = WriteConsoleInputW(handle, ir, numEvent, &written) ? rci_gotone : rci_error;
+                ret = write_console_input(handle, ir, numEvent, &written) ? rci_gotone : rci_error;
                 break;
             }
             break;
-- 
1.7.9.5


More information about the wine-patches mailing list