ntdll/kernel32: #27 take II

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a second take at console handles in ntdll. It includes corrections for latest Alexandre's remarks.

ChangeLog
- Adapted kernel32 so that it no longer (directly) manages console handles as wineserver handles
+ console input handle object is no longer waitable (input record
synchronisation is now implemented as a simple semaphore), and
remove FD_TYPE_CONSOLE from fd types in wineserver
+ console handles now always have their two lower bit set so one can
distinguish a console handle from a kernel object handle
+ implemented some undocumented kernel32 console related APIs
(CloseConsoleHandle, GetConsoleInputWaitHandle, OpenConsoleW,
VerifyConsoleIoHandle, DuplicateConsoleHandle)
+ allowed a few kernel32 APIs to take console pseudo-handles
(FlushFileBuffer, GetFileType, WaitFor*Object*,
+ simplified the console inheritance at process creation
+ in console tests, no longer create a console if one already exists



Notes:
- some ugly include directives (../kernel/kernel_private.h) were needed because some functions are not yet in dlls/kernel. We'll be able to get rid of those ugly directives as soon as files/functions are moved


A+
--
Eric Pouech
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel26/console.c dlls/kernel/console.c
--- dlls/kernel26/console.c	2003-05-13 19:29:57.000000000 +0200
+++ dlls/kernel/console.c	2003-06-18 20:57:25.000000000 +0200
@@ -48,12 +48,14 @@
 #include "wine/debug.h"
 #include "excpt.h"
 #include "console_private.h"
+#include "kernel_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(console);
 
 static UINT console_input_codepage;
 static UINT console_output_codepage;
 
+
 /* map input records to ASCII */
 static void input_records_WtoA( INPUT_RECORD *buffer, int count )
 {
@@ -195,11 +197,12 @@
     if (written) *written = 0;
     SERVER_START_REQ( write_console_input )
     {
-        req->handle = handle;
+        req->handle = console_handle_unmap(handle);
         wine_server_add_data( req, buffer, count * sizeof(INPUT_RECORD) );
         if ((ret = !wine_server_call_err( req )))
         {
             if (written) *written = reply->written;
+            ReleaseSemaphore( GetConsoleInputWaitHandle(), reply->written, NULL );
         }
     }
     SERVER_END_REQ;
@@ -266,7 +269,7 @@
         {
             SERVER_START_REQ( write_console_output )
             {
-                req->handle = hConsoleOutput;
+                req->handle = console_handle_unmap(hConsoleOutput);
                 req->x      = region->Left;
                 req->y      = region->Top + y;
                 req->mode   = CHAR_INFO_MODE_TEXTATTR;
@@ -348,7 +351,7 @@
 
     SERVER_START_REQ( write_console_output )
     {
-        req->handle = hConsoleOutput;
+        req->handle = console_handle_unmap(hConsoleOutput);
         req->x      = coord.X;
         req->y      = coord.Y;
         req->mode   = CHAR_INFO_MODE_ATTR;
@@ -412,7 +415,7 @@
 
     SERVER_START_REQ( fill_console_output )
     {
-        req->handle  = hConsoleOutput;
+        req->handle  = console_handle_unmap(hConsoleOutput);
         req->x       = coord.X;
         req->y       = coord.Y;
         req->mode    = CHAR_INFO_MODE_TEXT;
@@ -453,7 +456,7 @@
 
     SERVER_START_REQ( fill_console_output )
     {
-        req->handle    = hConsoleOutput;
+        req->handle    = console_handle_unmap(hConsoleOutput);
         req->x         = coord.X;
         req->y         = coord.Y;
         req->mode      = CHAR_INFO_MODE_ATTR;
@@ -507,7 +510,7 @@
 
     SERVER_START_REQ( read_console_output )
     {
-        req->handle = hConsoleOutput;
+        req->handle = console_handle_unmap(hConsoleOutput);
         req->x      = coord.X;
         req->y      = coord.Y;
         req->mode   = CHAR_INFO_MODE_TEXT;
@@ -536,7 +539,7 @@
 
     SERVER_START_REQ( read_console_output )
     {
-        req->handle = hConsoleOutput;
+        req->handle = console_handle_unmap(hConsoleOutput);
         req->x      = coord.X;
         req->y      = coord.Y;
         req->mode   = CHAR_INFO_MODE_ATTR;
@@ -596,7 +599,7 @@
         {
             SERVER_START_REQ( read_console_output )
             {
-                req->handle = hConsoleOutput;
+                req->handle = console_handle_unmap(hConsoleOutput);
                 req->x      = region->Left;
                 req->y      = region->Top + y;
                 req->mode   = CHAR_INFO_MODE_TEXTATTR;
@@ -667,7 +670,7 @@
     BOOL ret;
     SERVER_START_REQ( read_console_input )
     {
-        req->handle = handle;
+        req->handle = console_handle_unmap(handle);
         req->flush  = FALSE;
         wine_server_set_reply( req, buffer, count * sizeof(INPUT_RECORD) );
         if ((ret = !wine_server_call_err( req )))
@@ -688,7 +691,7 @@
     BOOL ret;
     SERVER_START_REQ( read_console_input )
     {
-        req->handle = handle;
+        req->handle = console_handle_unmap(handle);
         req->flush  = FALSE;
         if ((ret = !wine_server_call_err( req )))
         {
@@ -700,24 +703,50 @@
 }
 
 
-/***********************************************************************
- *            FlushConsoleInputBuffer   (KERNEL32.@)
+/******************************************************************************
+ * read_console_input
+ *
+ * Helper function for ReadConsole, ReadConsoleInput and FlushConsoleInputBuffer
+ *
+ * Returns 
+ *      0 for error, 1 for no INPUT_RECORD ready, 2 with INPUT_RECORD ready
  */
-BOOL WINAPI FlushConsoleInputBuffer( HANDLE handle )
+enum read_console_input_return {rci_error = 0, rci_timeout = 1, rci_gotone = 2};
+static enum read_console_input_return read_console_input(HANDLE handle, LPINPUT_RECORD ir, DWORD timeout)
 {
-    BOOL ret;
+    enum read_console_input_return      ret;
+
+    if (WaitForSingleObject(GetConsoleInputWaitHandle(), timeout) != WAIT_OBJECT_0)
+        return rci_timeout;
     SERVER_START_REQ( read_console_input )
     {
-        req->handle = handle;
-        req->flush  = TRUE;
-        ret = !wine_server_call_err( req );
+        req->handle = console_handle_unmap(handle);
+        req->flush = TRUE;
+        wine_server_set_reply( req, ir, sizeof(INPUT_RECORD) );
+        if (wine_server_call_err( req ) || !reply->read) ret = rci_error;
+        else ret = rci_gotone;
     }
     SERVER_END_REQ;
+
     return ret;
 }
 
 
 /***********************************************************************
+ *            FlushConsoleInputBuffer   (KERNEL32.@)
+ */
+BOOL WINAPI FlushConsoleInputBuffer( HANDLE handle )
+{
+    enum read_console_input_return      last;
+    INPUT_RECORD                        ir;
+
+    while ((last = read_console_input(handle, &ir, 0)) == rci_gotone);
+
+    return last == rci_timeout;
+}
+
+
+/***********************************************************************
  *            SetConsoleTitleA   (KERNEL32.@)
  */
 BOOL WINAPI SetConsoleTitleA( LPCSTR title )
@@ -996,30 +1025,6 @@
 }
 
 
-/******************************************************************************
- * read_console_input
- *
- * Helper function for ReadConsole, ReadConsoleInput and PeekConsoleInput
- */
-static BOOL read_console_input(HANDLE handle, LPINPUT_RECORD buffer, DWORD count,
-			       LPDWORD pRead, BOOL flush)
-{
-    BOOL	ret;
-    unsigned	read = 0;
-
-    SERVER_START_REQ( read_console_input )
-    {
-        req->handle = handle;
-        req->flush = flush;
-        wine_server_set_reply( req, buffer, count * sizeof(INPUT_RECORD) );
-        if ((ret = !wine_server_call_err( req ))) read = reply->read;
-    }
-    SERVER_END_REQ;
-    if (pRead) *pRead = read;
-    return ret;
-}
-
-
 /***********************************************************************
  *            ReadConsoleA   (KERNEL32.@)
  */
@@ -1072,23 +1077,26 @@
     else
     {
 	INPUT_RECORD 	ir;
-	DWORD 		count;
+        DWORD           timeout = INFINITE;
 
 	/* FIXME: should we read at least 1 char? The SDK does not say */
 	/* wait for at least one available input record (it doesn't mean we'll have
-	 * chars stored in xbuf...
+	 * chars stored in xbuf...)
 	 */
-	WaitForSingleObject(hConsoleInput, INFINITE);
-	for (charsread = 0; charsread < nNumberOfCharsToRead;)
+	charsread = 0;
+        do 
 	{
-	    if (!read_console_input(hConsoleInput, &ir, 1, &count, TRUE)) return FALSE;
-	    if (count && ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown &&
+	    if (read_console_input(hConsoleInput, &ir, timeout) != rci_gotone) break;
+            timeout = 0;
+	    if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown &&
 		ir.Event.KeyEvent.uChar.UnicodeChar &&
 		!(ir.Event.KeyEvent.dwControlKeyState & ENHANCED_KEY))
 	    {
 		xbuf[charsread++] = ir.Event.KeyEvent.uChar.UnicodeChar;
 	    }
-	}
+        } while (charsread < nNumberOfCharsToRead);
+        /* nothing has been read */
+        if (timeout == INFINITE) return FALSE;
     }
 
     if (lpNumberOfCharsRead) *lpNumberOfCharsRead = charsread;
@@ -1103,7 +1111,8 @@
 BOOL WINAPI ReadConsoleInputW(HANDLE hConsoleInput, LPINPUT_RECORD lpBuffer,
                               DWORD nLength, LPDWORD lpNumberOfEventsRead)
 {
-    DWORD count;
+    DWORD idx = 0;
+    DWORD timeout = INFINITE;
 
     if (!nLength)
     {
@@ -1112,17 +1121,12 @@
     }
 
     /* loop until we get at least one event */
-    for (;;)
-    {
-        WaitForSingleObject(hConsoleInput, INFINITE);
-	if (!read_console_input(hConsoleInput, lpBuffer, nLength, &count, TRUE))
-	    return FALSE;
-        if (count)
-        {
-            if (lpNumberOfEventsRead) *lpNumberOfEventsRead = count;
-            return TRUE;
-        }
-    }
+    while (read_console_input(hConsoleInput, &lpBuffer[idx], timeout) == rci_gotone &&
+           ++idx < nLength)
+        timeout = 0;
+
+    if (lpNumberOfEventsRead) *lpNumberOfEventsRead = idx;
+    return idx != 0;
 }
 
 
@@ -1152,7 +1156,7 @@
 
     SERVER_START_REQ( write_console_output )
     {
-        req->handle = hConsoleOutput;
+        req->handle = console_handle_unmap(hConsoleOutput);
         req->x      = coord.X;
         req->y      = coord.Y;
         req->mode   = CHAR_INFO_MODE_TEXT;
@@ -1480,7 +1484,7 @@
 
     SERVER_START_REQ(get_console_output_info)
     {
-        req->handle = hConsoleOutput;
+        req->handle = console_handle_unmap(hConsoleOutput);
         if ((ret = !wine_server_call_err( req )))
         {
             csbi->dwSize.X              = reply->width;
@@ -1536,7 +1540,7 @@
 
     SERVER_START_REQ(get_console_mode)
     {
-	req->handle = hcon;
+	req->handle = console_handle_unmap(hcon);
 	ret = !wine_server_call_err( req );
 	if (ret && mode) *mode = reply->mode;
     }
@@ -1569,7 +1573,7 @@
 
     SERVER_START_REQ(set_console_mode)
     {
-	req->handle = hcon;
+	req->handle = console_handle_unmap(hcon);
 	req->mode = mode;
 	ret = !wine_server_call_err( req );
     }
@@ -1598,7 +1602,7 @@
 
     SERVER_START_REQ( write_console_output )
     {
-        req->handle = hCon;
+        req->handle = console_handle_unmap(hCon);
         req->x      = pos->X;
         req->y      = pos->Y;
         req->mode   = CHAR_INFO_MODE_TEXTSTDATTR;
@@ -1828,7 +1832,7 @@
 
     SERVER_START_REQ(set_console_output_info)
     {
-        req->handle         = hcon;
+        req->handle         = console_handle_unmap(hcon);
         req->cursor_x       = pos.X;
         req->cursor_y       = pos.Y;
         req->mask           = SET_CONSOLE_OUTPUT_INFO_CURSOR_POS;
@@ -1888,7 +1892,7 @@
 
     SERVER_START_REQ(get_console_output_info)
     {
-        req->handle = hcon;
+        req->handle = console_handle_unmap(hcon);
         ret = !wine_server_call_err( req );
         if (ret && cinfo)
         {
@@ -1917,7 +1921,7 @@
 
     SERVER_START_REQ(set_console_output_info)
     {
-        req->handle         = hCon;
+        req->handle         = console_handle_unmap(hCon);
         req->cursor_size    = cinfo->dwSize;
         req->cursor_visible = cinfo->bVisible;
         req->mask           = SET_CONSOLE_OUTPUT_INFO_CURSOR_GEOM;
@@ -1956,7 +1960,7 @@
     }
     SERVER_START_REQ(set_console_output_info)
     {
-        req->handle         = hCon;
+        req->handle         = console_handle_unmap(hCon);
 	req->win_left       = p.Left;
 	req->win_top        = p.Top;
 	req->win_right      = p.Right;
@@ -1986,7 +1990,7 @@
 
     SERVER_START_REQ(set_console_output_info)
     {
-        req->handle = hConsoleOutput;
+        req->handle = console_handle_unmap(hConsoleOutput);
         req->attr   = wAttr;
         req->mask   = SET_CONSOLE_OUTPUT_INFO_ATTR;
         ret = !wine_server_call_err( req );
@@ -2013,7 +2017,7 @@
 
     SERVER_START_REQ(set_console_output_info)
     {
-        req->handle = hConsoleOutput;
+        req->handle = console_handle_unmap(hConsoleOutput);
         req->width  = dwSize.X;
         req->height = dwSize.Y;
         req->mask   = SET_CONSOLE_OUTPUT_INFO_SIZE;
@@ -2051,7 +2055,7 @@
 {
     SERVER_START_REQ( fill_console_output )
     {
-        req->handle    = hConsoleOutput;
+        req->handle    = console_handle_unmap(hConsoleOutput);
         req->mode      = CHAR_INFO_MODE_TEXTATTR;
         req->x         = i;
         req->y         = j;
@@ -2129,7 +2133,7 @@
     /* step 3: transfer the bits */
     SERVER_START_REQ(move_console_output)
     {
-        req->handle = hConsoleOutput;
+        req->handle = console_handle_unmap(hConsoleOutput);
 	req->x_src = lpScrollRect->Left;
 	req->y_src = lpScrollRect->Top;
 	req->x_dst = dst.Left;
@@ -2260,7 +2264,7 @@
     unsigned ret = FALSE;
     SERVER_START_REQ(get_console_input_info)
     {
-        req->handle = hConIn;
+        req->handle = console_handle_unmap(hConIn);
         if ((ret = !wine_server_call_err( req )))
             *mode = reply->edition_mode;
     }
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel26/editline.c dlls/kernel/editline.c
--- dlls/kernel26/editline.c	2003-02-19 21:10:45.000000000 +0100
+++ dlls/kernel/editline.c	2003-05-23 22:46:44.000000000 +0200
@@ -88,29 +88,10 @@
 
 static BOOL WCEL_Get(WCEL_Context* ctx, INPUT_RECORD* ir)
 {
-    DWORD		retv;
-
-    for (;;)
-    {
-	/* data available ? */
-	if (ReadConsoleInputW(ctx->hConIn, ir, 1, &retv) && retv == 1)
-	    return TRUE;
-	/* then wait... */
-	switch (WaitForSingleObject(ctx->hConIn, INFINITE))
-	{
-	case WAIT_OBJECT_0:
-	    break;
-	default:
-	    /* we have checked that hConIn was a console handle (could be sb) */
-	    ERR("Shouldn't happen\n");
-	    /* fall thru */
-	case WAIT_ABANDONED:
-	case WAIT_TIMEOUT:
-	    ctx->error = 1;
-	    ERR("hmm bad situation\n");
-	    return FALSE;
-	}
-    }
+    if (ReadConsoleInputW(ctx->hConIn, ir, 1, NULL)) return TRUE;
+    ERR("hmm bad situation\n");
+    ctx->error = 1;
+    return FALSE;
 }
 
 static inline void WCEL_Beep(WCEL_Context* ctx)
@@ -633,7 +614,7 @@
 static void WCEL_RepeatCount(WCEL_Context* ctx)
 {
 #if 0
-/* FIXME: wait untill all console code is in kernel32 */
+/* FIXME: wait until all console code is in kernel32 */
     INPUT_RECORD        ir;
     unsigned            repeat = 0;
 
@@ -822,11 +803,12 @@
 
     while (!ctx.done && !ctx.error && WCEL_Get(&ctx, &ir))
     {
-	if (ir.EventType != KEY_EVENT || !ir.Event.KeyEvent.bKeyDown) continue;
+	if (ir.EventType != KEY_EVENT) continue;
 	TRACE("key%s repeatCount=%u, keyCode=%02x scanCode=%02x char=%02x keyState=%08lx\n",
 	      ir.Event.KeyEvent.bKeyDown ? "Down" : "Up  ", ir.Event.KeyEvent.wRepeatCount,
 	      ir.Event.KeyEvent.wVirtualKeyCode, ir.Event.KeyEvent.wVirtualScanCode,
 	      ir.Event.KeyEvent.uChar.UnicodeChar, ir.Event.KeyEvent.dwControlKeyState);
+	if (!ir.Event.KeyEvent.bKeyDown) continue;
 
 /* EPP  	WCEL_Dump(&ctx, "before func"); */
 	ofs = ctx.ofs;
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel26/kernel32.spec dlls/kernel/kernel32.spec
--- dlls/kernel26/kernel32.spec	2003-06-14 09:30:10.000000000 +0200
+++ dlls/kernel/kernel32.spec	2003-06-18 20:28:01.000000000 +0200
@@ -913,7 +913,7 @@
 @ stub AddConsoleAliasW
 @ stub BaseAttachCompleteThunk
 @ stub BasepDebugDump
-@ stub CloseConsoleHandle
+@ stdcall CloseConsoleHandle(long)
 @ stub CmdBatNotification
 @ stub ConsoleMenuControl
 @ stub ConsoleSubst
@@ -941,7 +941,7 @@
 @ stub GetConsoleFontInfo
 @ stub GetConsoleFontSize
 @ stub GetConsoleHardwareState
-@ stub GetConsoleInputWaitHandle
+@ stdcall GetConsoleInputWaitHandle()
 @ stub GetCurrentConsoleFont
 @ stub GetNextVDMCommand
 @ stub GetNumberOfConsoleFonts
@@ -953,7 +953,7 @@
 @ stub HeapUsage
 @ stub InvalidateConsoleDIBits
 @ stdcall IsDebuggerPresent()
-@ stub OpenConsoleW
+@ stdcall OpenConsoleW(wstr long ptr long)
 @ stub QueryWin31IniFilesMappedToRegistry
 @ stub RegisterConsoleVDM
 @ stub RegisterWaitForInputIdle
@@ -976,7 +976,7 @@
 @ stub TrimVirtualBuffer
 @ stub VDMConsoleOperation
 @ stub VDMOperationStarted
-@ stub VerifyConsoleIoHandle
+@ stdcall VerifyConsoleIoHandle(long)
 @ stub VirtualBufferExceptionHandler
 @ stub WriteConsoleInputVDMA
 @ stub WriteConsoleInputVDMW
@@ -991,7 +991,7 @@
 @ stdcall CreateWaitableTimerA(ptr long str)
 @ stdcall CreateWaitableTimerW(ptr long wstr)
 @ stdcall DeleteFiber(ptr)
-@ stub DuplicateConsoleHandle
+@ stdcall DuplicateConsoleHandle(long long long long)
 @ stdcall FindFirstFileExA(str long ptr long ptr long)
 @ stdcall FindFirstFileExW(wstr long ptr long ptr long)
 @ stub GetConsoleInputExeNameA
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel26/kernel_private.h dlls/kernel/kernel_private.h
--- dlls/kernel26/kernel_private.h	1970-01-01 01:00:00.000000000 +0100
+++ dlls/kernel/kernel_private.h	2003-06-18 21:33:39.000000000 +0200
@@ -0,0 +1,47 @@
+/*
+ * Kernel32 undocumented and private functions definition
+ *
+ * Copyright 2003 Eric Pouech
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef __WINE_KERNEL_PRIVATE_H
+#define __WINE_KERNEL_PRIVATE_H
+
+HANDLE  WINAPI OpenConsoleW(LPCWSTR, DWORD, LPSECURITY_ATTRIBUTES, DWORD);
+BOOL    WINAPI VerifyConsoleIoHandle(HANDLE);
+HANDLE  WINAPI DuplicateConsoleHandle(HANDLE, DWORD, BOOL, DWORD);
+BOOL    WINAPI CloseConsoleHandle(HANDLE handle);
+HANDLE  WINAPI GetConsoleInputWaitHandle(void);
+
+static inline BOOL is_console_handle(HANDLE h)
+{
+    return h != INVALID_HANDLE_VALUE && ((DWORD)h & 3) == 3;
+}
+
+/* map a real wineserver handle onto a kernel32 console handle */
+static inline HANDLE console_handle_map(HANDLE h)
+{
+    return h != INVALID_HANDLE_VALUE ? (HANDLE)((DWORD)h ^ 3) : INVALID_HANDLE_VALUE;
+}
+
+/* map a kernel32 console handle onto a real wineserver handle */
+static inline HANDLE console_handle_unmap(HANDLE h)
+{
+    return h != INVALID_HANDLE_VALUE ? (HANDLE)((DWORD)h ^ 3) : INVALID_HANDLE_VALUE;
+}
+
+#endif
diff -u -N -r -x '*~' -x '.#*' -x CVS dlls/kernel26/tests/console.c dlls/kernel/tests/console.c
--- dlls/kernel26/tests/console.c	2003-05-13 06:46:54.000000000 +0200
+++ dlls/kernel/tests/console.c	2003-06-18 21:12:55.000000000 +0200
@@ -538,7 +538,7 @@
 
 START_TEST(console)
 {
-    HANDLE hCon;
+    HANDLE hConIn, hConOut;
     BOOL ret;
     CONSOLE_SCREEN_BUFFER_INFO	sbi;
 
@@ -548,16 +548,29 @@
      * Another solution would be to rerun the test under wineconsole with
      * the curses backend
      */
-    FreeConsole();
-    AllocConsole();
-    hCon = GetStdHandle(STD_OUTPUT_HANDLE);
-    ok(ret = GetConsoleScreenBufferInfo(hCon, &sbi), "Getting sb info");
+
+    hConIn = CreateFileA("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
+    hConOut = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
+
+    /* first, we need to be sure we're attached to a console */
+    if (hConIn == INVALID_HANDLE_VALUE || hConOut == INVALID_HANDLE_VALUE)
+    {
+        /* we're not attached to a console, let's do it */
+        AllocConsole();
+        hConIn = CreateFileA("CONIN$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
+        hConOut = CreateFileA("CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
+    }
+    /* now verify everything's ok */
+    ok(hConIn != INVALID_HANDLE_VALUE, "Opening ConIn");
+    ok(hConOut != INVALID_HANDLE_VALUE, "Opening ConOut");
+
+    ok(ret = GetConsoleScreenBufferInfo(hConOut, &sbi), "Getting sb info");
     if (!ret) return;
 
     /* Non interactive tests */
-    testCursor(hCon, sbi.dwSize);
+    testCursor(hConOut, sbi.dwSize);
     /* will test wrapped (on/off) & processed (on/off) strings output */
-    testWrite(hCon, sbi.dwSize);
+    testWrite(hConOut, sbi.dwSize);
     /* will test line scrolling at the bottom of the screen */
     /* testBottomScroll(); */
     /* will test all the scrolling operations */
diff -u -N -r -x '*~' -x '.#*' -x CVS files26/file.c files/file.c
--- files26/file.c	2003-06-14 09:30:11.000000000 +0200
+++ files/file.c	2003-06-18 21:11:05.000000000 +0200
@@ -70,6 +70,7 @@
 #include "heap.h"
 #include "msdos.h"
 #include "wincon.h"
+#include "../kernel/kernel_private.h" /* FIXME: to be changed when moved to kernel32 */
 
 #include "smb.h"
 #include "wine/unicode.h"
@@ -351,30 +352,124 @@
     return FILE_GetUnixHandleType( handle, access, NULL, NULL );
 }
 
-/*************************************************************************
- * 		FILE_OpenConsole
+/******************************************************************
+ *		OpenConsoleW            (KERNEL32.@)
  *
- * Open a handle to the current process console.
- * Returns 0 on failure.
+ * Undocumented
+ *      Open a handle to the current process console.
+ *      Returns INVALID_HANDLE_VALUE on failure.
  */
-static HANDLE FILE_OpenConsole( BOOL output, DWORD access, DWORD sharing, LPSECURITY_ATTRIBUTES sa )
+HANDLE WINAPI OpenConsoleW(LPCWSTR name, DWORD access, LPSECURITY_ATTRIBUTES sa,
+                           DWORD creation)
 {
+    static const WCHAR coninW[] = {'C','O','N','I','N','$',0};
+    static const WCHAR conoutW[] = {'C','O','N','O','U','T','$',0};
+    BOOL        output;
     HANDLE ret;
 
+    if (strcmpW(coninW, name) == 0) 
+        output = FALSE;
+    else if (strcmpW(conoutW, name) == 0) 
+        output = TRUE;
+    else
+    {
+        SetLastError(ERROR_INVALID_NAME);
+        return INVALID_HANDLE_VALUE;
+    }
+    if (creation != OPEN_EXISTING)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return INVALID_HANDLE_VALUE;
+    }
+
     SERVER_START_REQ( open_console )
     {
         req->from    = output;
         req->access  = access;
-	req->share   = sharing;
+	req->share   = FILE_SHARE_READ | FILE_SHARE_WRITE;
         req->inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
         SetLastError(0);
         wine_server_call_err( req );
         ret = reply->handle;
     }
     SERVER_END_REQ;
+    return ret ? console_handle_map(ret) : INVALID_HANDLE_VALUE;
+}
+
+/******************************************************************
+ *		VerifyConsoleIoHandle            (KERNEL32.@)
+ *
+ * Undocumented
+ */
+BOOL WINAPI VerifyConsoleIoHandle(HANDLE handle)
+{
+    BOOL ret;
+
+    if (!is_console_handle(handle)) return FALSE;
+    SERVER_START_REQ(get_console_mode)
+    {
+	req->handle = console_handle_unmap(handle);
+	ret = !wine_server_call_err( req );
+    }
+    SERVER_END_REQ;
     return ret;
 }
 
+/******************************************************************
+ *		DuplicateConsoleHandle            (KERNEL32.@)
+ *
+ * Undocumented
+ */
+HANDLE WINAPI DuplicateConsoleHandle(HANDLE handle, DWORD access, BOOL inherit,
+                                     DWORD options)
+{
+    HANDLE      ret;
+
+    if (!is_console_handle(handle) ||
+        !DuplicateHandle(GetCurrentProcess(), console_handle_unmap(handle), 
+                         GetCurrentProcess(), &ret, access, inherit, options))
+        return INVALID_HANDLE_VALUE;
+    return console_handle_map(ret);
+}
+
+/******************************************************************
+ *		CloseConsoleHandle            (KERNEL32.@)
+ *
+ * Undocumented
+ */
+BOOL WINAPI CloseConsoleHandle(HANDLE handle)
+{
+    if (!is_console_handle(handle)) 
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    return CloseHandle(console_handle_unmap(handle));
+}
+
+/******************************************************************
+ *		GetConsoleInputWaitHandle            (KERNEL32.@)
+ *
+ * Undocumented
+ */
+HANDLE WINAPI GetConsoleInputWaitHandle(void)
+{
+    static HANDLE console_wait_event;
+ 
+    /* FIXME: this is not thread safe */
+    if (!console_wait_event)
+    {
+        SERVER_START_REQ(get_console_wait_event)
+        {
+            if (!wine_server_call_err( req )) console_wait_event = reply->handle;
+        }
+        SERVER_END_REQ;
+    }
+    return console_wait_event;
+}
+/* end of FIXME */
+
+
 /* FIXME: those routines defined as pointers are needed, because this file is
  * currently compiled into NTDLL whereas it belongs to kernel32.
  * this shall go away once all the DLL separation process is done
@@ -630,14 +725,9 @@
     }
 
     /* Open a console for CONIN$ or CONOUT$ */
-    if (!strcmpiW(filename, coninW))
+    if (!strcmpiW(filename, coninW) || !strcmpiW(filename, conoutW))
     {
-        ret = FILE_OpenConsole( FALSE, access, sharing, sa );
-        goto done;
-    }
-    if (!strcmpiW(filename, conoutW))
-    {
-        ret = FILE_OpenConsole( TRUE, access, sharing, sa );
+        ret = OpenConsoleW(filename, access, sa, creation);
         goto done;
     }
 
@@ -1807,6 +1897,9 @@
     if (bytesRead) *bytesRead = 0;  /* Do this before anything else */
     if (!bytesToRead) return TRUE;
 
+    if (is_console_handle(hFile))
+	return FILE_ReadConsole(hFile, buffer, bytesToRead, bytesRead, NULL);
+
     unix_handle = FILE_GetUnixHandleType( hFile, GENERIC_READ, &type, &flags );
 
     if (flags & FD_FLAG_OVERLAPPED)
@@ -1845,9 +1938,6 @@
     case FD_TYPE_SMB:
         return SMB_ReadFile(hFile, buffer, bytesToRead, bytesRead, NULL);
 
-    case FD_TYPE_CONSOLE:
-	return FILE_ReadConsole(hFile, buffer, bytesToRead, bytesRead, NULL);
-
     case FD_TYPE_DEFAULT:
         /* normal unix files */
         if (unix_handle == -1) return FALSE;
@@ -2031,6 +2121,9 @@
     if (bytesWritten) *bytesWritten = 0;  /* Do this before anything else */
     if (!bytesToWrite) return TRUE;
 
+    if (is_console_handle(hFile))
+	return FILE_WriteConsole(hFile, buffer, bytesToWrite, bytesWritten, NULL);
+
     unix_handle = FILE_GetUnixHandleType( hFile, GENERIC_WRITE, &type, &flags );
 
     if (flags & FD_FLAG_OVERLAPPED)
@@ -2062,11 +2155,6 @@
 
     switch(type)
     {
-    case FD_TYPE_CONSOLE:
-	TRACE("%p %s %ld %p %p\n", hFile, debugstr_an(buffer, bytesToWrite), bytesToWrite,
-	      bytesWritten, overlapped );
-	return FILE_WriteConsole(hFile, buffer, bytesToWrite, bytesWritten, NULL);
-
     case FD_TYPE_DEFAULT:
         if (unix_handle == -1) return FALSE;
 
@@ -2366,6 +2454,13 @@
     NTSTATUS            nts;
     IO_STATUS_BLOCK     ioblk;
 
+    if (is_console_handle( hFile ))
+    {
+        /* this will fail (as expected) for an output handle */
+        /* FIXME: wait until FlushFileBuffers is moved to dll/kernel */
+        /* return FlushConsoleInputBuffer( hFile ); */
+        return TRUE;
+    }
     nts = NtFlushBuffersFile( hFile, &ioblk );
     if (nts != STATUS_SUCCESS)
     {
@@ -2473,6 +2568,10 @@
 DWORD WINAPI GetFileType( HANDLE hFile )
 {
     DWORD ret = FILE_TYPE_UNKNOWN;
+
+    if (is_console_handle( hFile ))
+        return FILE_TYPE_CHAR;
+
     SERVER_START_REQ( get_file_info )
     {
         req->handle = hFile;
diff -u -N -r -x '*~' -x '.#*' -x CVS programs/wineconsole26/wineconsole.c programs/wineconsole/wineconsole.c
--- programs/wineconsole26/wineconsole.c	2003-06-18 08:01:57.000000000 +0200
+++ programs/wineconsole/wineconsole.c	2003-06-18 20:28:27.000000000 +0200
@@ -535,6 +535,7 @@
     DWORD		ret;
     struct config_data  cfg;
     STARTUPINFOW        si;
+    HANDLE              sem;
 
     data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*data));
     if (!data) return 0;
@@ -563,6 +564,7 @@
         /* should always be defined */
     }
 
+    sem = CreateSemaphore(NULL, 0, 65536, NULL);
     /* the handles here are created without the whistles and bells required by console
      * (mainly because wineconsole doesn't need it)
      * - they are not inheritable
@@ -570,9 +572,11 @@
      */
     SERVER_START_REQ(alloc_console)
     {
-        req->access  = GENERIC_READ | GENERIC_WRITE;
-        req->inherit = FALSE;
-	req->pid     = pid;
+        req->access     = GENERIC_READ | GENERIC_WRITE;
+        req->inherit    = FALSE;
+	req->pid        = pid;
+        req->wait_event = sem;
+
         ret = !wine_server_call_err( req );
         data->hConIn = (HANDLE)reply->handle_in;
 	data->hSynchro = (HANDLE)reply->event;
diff -u -N -r -x '*~' -x '.#*' -x CVS scheduler26/handle.c scheduler/handle.c
--- scheduler26/handle.c	2003-05-13 22:49:11.000000000 +0200
+++ scheduler/handle.c	2003-05-23 22:03:16.000000000 +0200
@@ -32,6 +32,7 @@
 #include "wine/server.h"
 #include "winerror.h"
 #include "wine/debug.h"
+#include "../kernel/kernel_private.h"  /* FIXME: to be changed when moving file to dlls/kernel */
 
 WINE_DEFAULT_DEBUG_CHANNEL(win32);
 
@@ -49,6 +50,9 @@
         (handle == (HANDLE)STD_ERROR_HANDLE))
         handle = GetStdHandle( (DWORD)handle );
 
+    if (is_console_handle(handle))
+        return CloseConsoleHandle(handle);
+
     status = NtClose( handle );
     if (status) SetLastError( RtlNtStatusToDosError(status) );
     return !status;
@@ -118,8 +122,22 @@
                              HANDLE dest_process, HANDLE *dest,
                              DWORD access, BOOL inherit, DWORD options )
 {
-    NTSTATUS status = NtDuplicateObject( source_process, source, dest_process, dest,
-                                         access, inherit ? OBJ_INHERIT : 0, options );
+    NTSTATUS status;
+
+    if (is_console_handle(source))
+    {
+        /* FIXME: this test is not sufficient, we need to test process ids, not handles */
+        if (source_process != dest_process ||
+            source_process != GetCurrentProcess())
+        {
+            SetLastError(ERROR_INVALID_PARAMETER);
+            return FALSE;
+        }
+        *dest = DuplicateConsoleHandle( source, access, inherit, options );
+        return (*dest != INVALID_HANDLE_VALUE);
+    }
+    status = NtDuplicateObject( source_process, source, dest_process, dest,
+                                access, inherit ? OBJ_INHERIT : 0, options );
     if (status) SetLastError( RtlNtStatusToDosError(status) );
     return !status;
 }
diff -u -N -r -x '*~' -x '.#*' -x CVS scheduler26/process.c scheduler/process.c
--- scheduler26/process.c	2003-06-18 21:51:18.000000000 +0200
+++ scheduler/process.c	2003-06-18 21:34:51.000000000 +0200
@@ -47,6 +47,7 @@
 #include "wine/server.h"
 #include "options.h"
 #include "wine/debug.h"
+#include "../kernel/kernel_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(process);
 WINE_DECLARE_DEBUG_CHANNEL(server);
@@ -330,19 +329,25 @@
     /* Create the process heap */
     current_process.heap = HeapCreate( HEAP_GROWABLE, 0, 0 );
 
-    if (main_create_flags == 0 &&
-	process_pmts.hStdInput  == 0 &&
-	process_pmts.hStdOutput == 0 &&
-	process_pmts.hStdError  == 0)
-    {
-	/* This is wine specific:
-         * no parent, and no new console requested, create a simple console with bare handles to
-	 * unix stdio input & output streams (aka simple console)
+    if (info_size == 0)
+    {
+	/* This is wine specific: we have no parent (we're started from unix)
+         * so, create a simple console with bare handles to unix stdio 
+         * input & output streams (aka simple console)
 	 */
         wine_server_fd_to_handle( 0, GENERIC_READ|SYNCHRONIZE,  TRUE, &process_pmts.hStdInput );
         wine_server_fd_to_handle( 1, GENERIC_WRITE|SYNCHRONIZE, TRUE, &process_pmts.hStdOutput );
         wine_server_fd_to_handle( 1, GENERIC_WRITE|SYNCHRONIZE, TRUE, &process_pmts.hStdError );
     }
+    else
+    {
+        if (VerifyConsoleIoHandle(console_handle_map(process_pmts.hStdInput)))
+            process_pmts.hStdInput = console_handle_map(process_pmts.hStdInput);
+        if (VerifyConsoleIoHandle(console_handle_map(process_pmts.hStdOutput)))
+            process_pmts.hStdOutput = console_handle_map(process_pmts.hStdOutput);
+        if (VerifyConsoleIoHandle(console_handle_map(process_pmts.hStdError)))
+            process_pmts.hStdError = console_handle_map(process_pmts.hStdError);
+    }
 
     /* Now we can use the pthreads routines */
     PTHREAD_init_done();
@@ -955,6 +958,20 @@
             req->hstderr = GetStdHandle( STD_ERROR_HANDLE );
         }
 
+        if ((flags & (CREATE_NEW_CONSOLE | DETACHED_PROCESS)) != 0)
+        {
+            /* this is temporary (for console handles). We have no way to control that the handle is invalid in child process otherwise */
+            if (is_console_handle(req->hstdin))  req->hstdin  = INVALID_HANDLE_VALUE;
+            if (is_console_handle(req->hstdout)) req->hstdout = INVALID_HANDLE_VALUE;
+            if (is_console_handle(req->hstderr)) req->hstderr = INVALID_HANDLE_VALUE;
+        }
+        else
+        {
+            if (is_console_handle(req->hstdin))  req->hstdin  = console_handle_unmap(req->hstdin);
+            if (is_console_handle(req->hstdout)) req->hstdout = console_handle_unmap(req->hstdout);
+            if (is_console_handle(req->hstderr)) req->hstderr = console_handle_unmap(req->hstderr);
+        }
+
         if (GetLongPathNameA( filename, buf, MAX_PATH ))
             nameptr = buf;
         else
diff -u -N -r -x '*~' -x '.#*' -x CVS scheduler26/synchro.c scheduler/synchro.c
--- scheduler26/synchro.c	2003-03-31 21:34:14.000000000 +0200
+++ scheduler/synchro.c	2003-05-23 22:11:09.000000000 +0200
@@ -22,6 +22,7 @@
 
 #include "winbase.h"
 #include "winternl.h"
+#include "../kernel/kernel_private.h" /* FIXME: to be changed when moving file to dlls/kernel */
 
 
 /***********************************************************************
@@ -80,10 +81,39 @@
                                        BOOL alertable )
 {
     NTSTATUS status;
+    HANDLE hloc[MAXIMUM_WAIT_OBJECTS];
+    int i;
+
+    if (count >= MAXIMUM_WAIT_OBJECTS)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return WAIT_FAILED;
+    }
+    for (i = 0; i < count; i++)
+    {
+        if ((handles[i] == (HANDLE)STD_INPUT_HANDLE) ||
+            (handles[i] == (HANDLE)STD_OUTPUT_HANDLE) ||
+            (handles[i] == (HANDLE)STD_ERROR_HANDLE))
+            hloc[i] = GetStdHandle( (DWORD)handles[i] );
+        else
+            hloc[i] = handles[i];
+
+        /* yes, even screen buffer console handles are waitable, and are
+         * handled as a handle to the console itself !!
+         */
+        if (is_console_handle(hloc[i]))
+        {
+            if (!VerifyConsoleIoHandle(hloc[i]))
+            {
+                return FALSE;
+            }
+            hloc[i] = GetConsoleInputWaitHandle();
+        }
+    }
 
     if (timeout == INFINITE)
     {
-        status = NtWaitForMultipleObjects( count, handles, wait_all, alertable, NULL );
+        status = NtWaitForMultipleObjects( count, hloc, wait_all, alertable, NULL );
     }
     else
     {
@@ -91,7 +121,7 @@
 
         time.QuadPart = timeout * (ULONGLONG)10000;
         time.QuadPart = -time.QuadPart;
-        status = NtWaitForMultipleObjects( count, handles, wait_all, alertable, &time );
+        status = NtWaitForMultipleObjects( count, hloc, wait_all, alertable, &time );
     }
 
     if (HIWORD(status))  /* is it an error code? */
diff -u -N -r -x '*~' -x '.#*' -x CVS server26/console.c server/console.c
--- server26/console.c	2003-05-10 22:40:04.000000000 +0200
+++ server/console.c	2003-06-18 20:47:15.000000000 +0200
@@ -35,18 +35,16 @@
 #include "unicode.h"
 #include "console.h"
 
-
 static void console_input_dump( struct object *obj, int verbose );
 static void console_input_destroy( struct object *obj );
-static int console_input_signaled( struct object *obj, struct thread *thread );
 
 static const struct object_ops console_input_ops =
 {
     sizeof(struct console_input),     /* size */
     console_input_dump,               /* dump */
-    add_queue,                        /* add_queue */
-    remove_queue,                     /* remove_queue */
-    console_input_signaled,           /* signaled */
+    no_add_queue,                     /* add_queue */
+    NULL,                             /* remove_queue */
+    NULL,                             /* signaled */
     no_satisfied,                     /* satisfied */
     no_get_fd,                        /* get_fd */
     console_input_destroy             /* destroy */
@@ -205,7 +203,7 @@
     return evt;
 }
 
-static struct object *create_console_input( struct thread* renderer )
+static struct object *create_console_input( struct thread* renderer, struct object* wait_obj )
 {
     struct console_input *console_input;
 
@@ -224,6 +222,7 @@
     console_input->history_index = 0;
     console_input->history_mode  = 0;
     console_input->edition_mode  = 0;
+    console_input->wait_obj      = wait_obj;
 
     if (!console_input->history || !console_input->evt)
     {
@@ -368,11 +367,6 @@
     }
 }
 
-int is_console_object( struct object *obj )
-{
-    return (obj->ops == &console_input_ops || obj->ops == &screen_buffer_ops);
-}
-
 static struct console_input* console_input_get( obj_handle_t handle, unsigned access )
 {
     struct console_input*	console = 0;
@@ -390,14 +384,6 @@
     return console;
 }
 
-/* check if a console input is signaled: yes if non read input records */
-static int console_input_signaled( struct object *obj, struct thread *thread )
-{
-    struct console_input *console = (struct console_input *)obj;
-    assert( obj->ops == &console_input_ops );
-    return console->recnum ? 1 : 0;
-}
-
 struct console_signal_info {
     struct console_input        *console;
     process_id_t                 group;
@@ -957,6 +943,7 @@
 
     release_object( console_in->evt );
     console_in->evt = NULL;
+    release_object( console_in->wait_obj );
 
     for (i = 0; i < console_in->history_size; i++)
 	if (console_in->history[i]) free( console_in->history[i] );
@@ -1222,6 +1209,7 @@
     struct process *process;
     struct process *renderer = current->process;
     struct console_input *console;
+    struct object *wait_event;
 
     process = (req->pid) ? get_process_from_id( req->pid ) :
               (struct process *)grab_object( renderer->parent );
@@ -1234,8 +1222,13 @@
         set_error( STATUS_ACCESS_DENIED );
         goto the_end;
     }
-
-    if ((console = (struct console_input*)create_console_input( current )))
+    wait_event = get_handle_obj( renderer, req->wait_event, 0, NULL);
+    if (!wait_event)
+    {
+        set_error( STATUS_INVALID_PARAMETER );
+        goto the_end;
+    }
+    if ((console = (struct console_input*)create_console_input( current, wait_event )))
     {
         if ((in = alloc_handle( renderer, console, req->access, req->inherit )))
         {
@@ -1512,7 +1505,36 @@
     group = req->group_id ? req->group_id : current->process->group_id;
 
     if (!group)
-        set_error( STATUS_INVALID_PARAMETER);
+        set_error( STATUS_INVALID_PARAMETER );
     else
         propagate_console_signal( current->process->console, req->signal, group );
 }
+
+/* get console which renderer is 'current' */
+static int cgwe_enum( struct process* process, void* user)
+{
+    if (process->console && process->console->renderer == current)
+    {
+        *(struct console_input**)user = process->console;
+        return 1;
+    }
+    return 0;
+}
+
+DECL_HANDLER(get_console_wait_event)
+{
+    struct console_input* console = NULL;
+
+    if (current->process->console && current->process->console->renderer)
+        console = (struct console_input*)grab_object( (struct object*)current->process->console );
+    else enum_processes(cgwe_enum, &console);
+
+    if (console)
+    {
+        reply->handle = alloc_handle( current->process, console->wait_obj, 
+                                      SEMAPHORE_ALL_ACCESS, FALSE);
+        release_object( console );
+    }
+    else set_error( STATUS_INVALID_PARAMETER );
+}
+
diff -u -N -r -x '*~' -x '.#*' -x CVS server26/console.h server/console.h
--- server26/console.h	2003-05-10 22:40:04.000000000 +0200
+++ server/console.h	2003-05-23 15:43:03.000000000 +0200
@@ -42,12 +42,12 @@
     int                          history_index; /* number of used entries in history array */
     int                          history_mode;  /* mode of history (non zero means remove doubled strings */
     int                          edition_mode;  /* index to edition mode flavors */
+    struct object               *wait_obj;      /* object to wait on for input queue */
 };
 
 /* console functions */
 
 extern void inherit_console(struct thread *parent_thread, struct process *process, obj_handle_t hconin);
 extern int free_console( struct process *process );
-extern int is_console_object( struct object *obj );
 
 #endif  /* __WINE_SERVER_CONSOLE_H */
diff -u -N -r -x '*~' -x '.#*' -x CVS server26/fd.c server/fd.c
--- server26/fd.c	2003-05-15 20:34:06.000000000 +0200
+++ server/fd.c	2003-05-23 15:43:26.000000000 +0200
@@ -42,7 +42,6 @@
 #include "handle.h"
 #include "process.h"
 #include "request.h"
-#include "console.h"
 
 /* Because of the stupid Posix locking semantics, we need to keep
  * track of all file descriptors referencing a given file, and not
@@ -1035,16 +1034,6 @@
         reply->type = fd->fd_ops->get_file_info( fd, NULL, &reply->flags );
         release_object( fd );
     }
-    else  /* check for console handle (FIXME: should be done in the client) */
-    {
-        struct object *obj;
-
-        if ((obj = get_handle_obj( current->process, req->handle, req->access, NULL )))
-        {
-            if (is_console_object( obj )) reply->type = FD_TYPE_CONSOLE;
-            release_object( obj );
-        }
-    }
 }
 
 /* get a file information */
diff -u -N -r -x '*~' -x '.#*' -x CVS server26/process.c server/process.c
--- server26/process.c	2003-03-18 21:42:00.000000000 +0100
+++ server/process.c	2003-05-24 20:12:26.000000000 +0200
@@ -221,40 +221,11 @@
     }
     if (info)
     {
-        if (!info->inherit_all && !info->use_handles)
-        {
-            /* duplicate the handle from the parent into this process */
-            reply->hstdin  = duplicate_handle( parent_thread->process, info->hstdin, process,
-                                               0, TRUE, DUPLICATE_SAME_ACCESS );
-            reply->hstdout = duplicate_handle( parent_thread->process, info->hstdout, process,
-                                               0, TRUE, DUPLICATE_SAME_ACCESS );
-            reply->hstderr = duplicate_handle( parent_thread->process, info->hstderr, process,
-                                               0, TRUE, DUPLICATE_SAME_ACCESS );
-        }
-        else
-        {
-            reply->hstdin  = info->hstdin;
-            reply->hstdout = info->hstdout;
-            reply->hstderr = info->hstderr;
-        }
-    }
-    else
-    {
-        if (process->console)
-        {
-            reply->hstdin  = alloc_handle( process, process->console,
-                                           GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 1 );
-            reply->hstdout = alloc_handle( process, process->console->active,
-                                           GENERIC_READ | GENERIC_WRITE, 1 );
-            reply->hstderr = alloc_handle( process, process->console->active,
-                                           GENERIC_READ | GENERIC_WRITE, 1 );
-        }
-        else
-        {
-            /* no parent, let the caller decide what to do */
-            reply->hstdin = reply->hstdout = reply->hstderr = 0;
-        }
+        reply->hstdin  = info->hstdin;
+        reply->hstdout = info->hstdout;
+        reply->hstderr = info->hstderr;
     }
+    else reply->hstdin = reply->hstdout = reply->hstderr = INVALID_HANDLE_VALUE;
     /* some handles above may have been invalid; this is not an error */
     if (get_error() == STATUS_INVALID_HANDLE) clear_error();
     return 1;
diff -u -N -r -x '*~' -x '.#*' -x CVS server26/protocol.def server/protocol.def
--- server26/protocol.def	2003-06-18 21:46:42.000000000 +0200
+++ server/protocol.def	2003-06-18 20:28:29.000000000 +0200
@@ -627,7 +627,6 @@
 {
     FD_TYPE_INVALID,
     FD_TYPE_DEFAULT,
-    FD_TYPE_CONSOLE,
     FD_TYPE_SOCKET,
     FD_TYPE_SMB
 };
@@ -776,6 +775,7 @@
     unsigned int access;        /* wanted access rights */
     int          inherit;       /* inherit flag */
     process_id_t pid;           /* pid of process which shall be attached to the console */
+    obj_handle_t wait_event;    /* semaphore for number of active input events */
 @REPLY
     obj_handle_t handle_in;     /* handle to console input */
     obj_handle_t event;         /* handle to renderer events change notification */
@@ -851,6 +851,12 @@
 @END
 
 
+/* Get the input queue wait event */
+@REQ(get_console_wait_event)
+@REPLY
+    obj_handle_t handle;
+@END
+
 /* Get a console mode (input or output) */
 @REQ(get_console_mode)
     obj_handle_t handle;        /* handle to the console */

[Index of Archives]     [Gimp for Windows]     [Red Hat]     [Samba]     [Yosemite Camping]     [Graphics Cards]     [Wine Home]

  Powered by Linux