- 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 removed
  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
oldstable
Eric Pouech 2003-06-21 02:07:10 +00:00 committed by Alexandre Julliard
parent 64a41a2842
commit 412d37f6e6
18 changed files with 465 additions and 224 deletions

View File

@ -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 )
{
@ -189,20 +191,22 @@ BOOL WINAPI WriteConsoleInputW( HANDLE handle, const INPUT_RECORD *buffer,
DWORD count, LPDWORD written )
{
BOOL ret;
DWORD w;
TRACE("(%p,%p,%ld,%p)\n", handle, buffer, count, written);
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;
}
if ((ret = !wine_server_call_err( req ))) w = reply->written;
}
SERVER_END_REQ;
if (ret)
{
ReleaseSemaphore( GetConsoleInputWaitHandle(), w, NULL );
if (written) *written = w;
}
return ret;
}
@ -266,7 +270,7 @@ BOOL WINAPI WriteConsoleOutputW( HANDLE hConsoleOutput, const CHAR_INFO *lpBuffe
{
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 +352,7 @@ BOOL WINAPI WriteConsoleOutputAttribute( HANDLE hConsoleOutput, CONST WORD *attr
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 +416,7 @@ BOOL WINAPI FillConsoleOutputCharacterW( HANDLE hConsoleOutput, WCHAR ch, DWORD
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 +457,7 @@ BOOL WINAPI FillConsoleOutputAttribute( HANDLE hConsoleOutput, WORD attr, DWORD
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 +511,7 @@ BOOL WINAPI ReadConsoleOutputCharacterW( HANDLE hConsoleOutput, LPWSTR buffer, D
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 +540,7 @@ BOOL WINAPI ReadConsoleOutputAttribute(HANDLE hConsoleOutput, LPWORD lpAttribute
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 +600,7 @@ BOOL WINAPI ReadConsoleOutputW( HANDLE hConsoleOutput, LPCHAR_INFO lpBuffer, COO
{
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 +671,7 @@ BOOL WINAPI PeekConsoleInputW( HANDLE handle, LPINPUT_RECORD buffer, DWORD count
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 +692,7 @@ BOOL WINAPI GetNumberOfConsoleInputEvents( HANDLE handle, LPDWORD nrofevents )
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,20 +704,46 @@ BOOL WINAPI GetNumberOfConsoleInputEvents( HANDLE handle, LPDWORD nrofevents )
}
/******************************************************************************
* 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
*/
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)
{
enum read_console_input_return ret;
if (WaitForSingleObject(GetConsoleInputWaitHandle(), timeout) != WAIT_OBJECT_0)
return rci_timeout;
SERVER_START_REQ( read_console_input )
{
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 )
{
BOOL ret;
SERVER_START_REQ( read_console_input )
{
req->handle = handle;
req->flush = TRUE;
ret = !wine_server_call_err( req );
}
SERVER_END_REQ;
return ret;
enum read_console_input_return last;
INPUT_RECORD ir;
while ((last = read_console_input(handle, &ir, 0)) == rci_gotone);
return last == rci_timeout;
}
@ -990,30 +1020,6 @@ BOOL WINAPI AllocConsole(void)
}
/******************************************************************************
* 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.@)
*/
@ -1066,23 +1072,26 @@ BOOL WINAPI ReadConsoleW(HANDLE hConsoleInput, LPVOID lpBuffer,
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;
@ -1097,7 +1106,8 @@ BOOL WINAPI ReadConsoleW(HANDLE hConsoleInput, LPVOID lpBuffer,
BOOL WINAPI ReadConsoleInputW(HANDLE hConsoleInput, LPINPUT_RECORD lpBuffer,
DWORD nLength, LPDWORD lpNumberOfEventsRead)
{
DWORD count;
DWORD idx = 0;
DWORD timeout = INFINITE;
if (!nLength)
{
@ -1106,17 +1116,12 @@ BOOL WINAPI ReadConsoleInputW(HANDLE hConsoleInput, LPINPUT_RECORD lpBuffer,
}
/* 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;
}
@ -1146,7 +1151,7 @@ BOOL WINAPI WriteConsoleOutputCharacterW( HANDLE hConsoleOutput, LPCWSTR str, DW
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;
@ -1474,7 +1479,7 @@ BOOL WINAPI GetConsoleScreenBufferInfo(HANDLE hConsoleOutput, LPCONSOLE_SCREEN_B
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;
@ -1530,7 +1535,7 @@ BOOL WINAPI GetConsoleMode(HANDLE hcon, LPDWORD mode)
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;
}
@ -1563,7 +1568,7 @@ BOOL WINAPI SetConsoleMode(HANDLE hcon, DWORD mode)
SERVER_START_REQ(set_console_mode)
{
req->handle = hcon;
req->handle = console_handle_unmap(hcon);
req->mode = mode;
ret = !wine_server_call_err( req );
}
@ -1592,7 +1597,7 @@ int CONSOLE_WriteChars(HANDLE hCon, LPCWSTR lpBuffer, int nc, COORD* pos)
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;
@ -1822,7 +1827,7 @@ BOOL WINAPI SetConsoleCursorPosition(HANDLE hcon, COORD pos)
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;
@ -1882,7 +1887,7 @@ BOOL WINAPI GetConsoleCursorInfo(HANDLE hcon, LPCONSOLE_CURSOR_INFO cinfo)
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)
{
@ -1911,7 +1916,7 @@ BOOL WINAPI SetConsoleCursorInfo(HANDLE hCon, LPCONSOLE_CURSOR_INFO cinfo)
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;
@ -1950,7 +1955,7 @@ BOOL WINAPI SetConsoleWindowInfo(HANDLE hCon, BOOL bAbsolute, LPSMALL_RECT windo
}
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;
@ -1980,7 +1985,7 @@ BOOL WINAPI SetConsoleTextAttribute(HANDLE hConsoleOutput, WORD wAttr)
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 );
@ -2007,7 +2012,7 @@ BOOL WINAPI SetConsoleScreenBufferSize(HANDLE hConsoleOutput, COORD dwSize)
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;
@ -2045,7 +2050,7 @@ void CONSOLE_FillLineUniform(HANDLE hConsoleOutput, int i, int j, int len, LPCHA
{
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;
@ -2123,7 +2128,7 @@ BOOL WINAPI ScrollConsoleScreenBufferW(HANDLE hConsoleOutput, LPSMALL_RECT lpScr
/* 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;
@ -2254,7 +2259,7 @@ BOOL CONSOLE_GetEditionMode(HANDLE hConIn, int* mode)
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;
}

View File

@ -88,29 +88,10 @@ static void WCEL_Dump(WCEL_Context* ctx, const char* pfx)
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_Redraw(WCEL_Context* ctx)
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 @@ WCHAR* CONSOLE_Readline(HANDLE hConsoleIn)
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;

View File

@ -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

View File

@ -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

View File

@ -538,7 +538,7 @@ static void testScroll(HANDLE hCon, COORD sbSize)
START_TEST(console)
{
HANDLE hCon;
HANDLE hConIn, hConOut;
BOOL ret;
CONSOLE_SCREEN_BUFFER_INFO sbi;
@ -548,16 +548,29 @@ START_TEST(console)
* 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 */

View File

@ -70,6 +70,7 @@
#include "heap.h"
#include "msdos.h"
#include "wincon.h"
#include "../kernel/kernel_private.h"
#include "smb.h"
#include "wine/unicode.h"
@ -351,30 +352,124 @@ int FILE_GetUnixHandle( HANDLE handle, DWORD access )
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 @@ HANDLE WINAPI CreateFileW( LPCWSTR filename, DWORD access, DWORD sharing,
}
/* 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 @@ BOOL WINAPI ReadFile( HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
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 @@ BOOL WINAPI ReadFile( HANDLE hFile, LPVOID buffer, DWORD bytesToRead,
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 @@ BOOL WINAPI WriteFile( HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
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 @@ BOOL WINAPI WriteFile( HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite,
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 @@ BOOL WINAPI FlushFileBuffers( HANDLE hFile )
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 @@ BOOL WINAPI DeleteFileA( LPCSTR path )
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;

View File

@ -815,7 +815,6 @@ enum fd_type
{
FD_TYPE_INVALID,
FD_TYPE_DEFAULT,
FD_TYPE_CONSOLE,
FD_TYPE_SOCKET,
FD_TYPE_SMB
};
@ -1037,6 +1036,7 @@ struct alloc_console_request
unsigned int access;
int inherit;
process_id_t pid;
obj_handle_t wait_event;
};
struct alloc_console_reply
{
@ -1132,6 +1132,17 @@ struct open_console_reply
struct get_console_wait_event_request
{
struct request_header __header;
};
struct get_console_wait_event_reply
{
struct reply_header __header;
obj_handle_t handle;
};
struct get_console_mode_request
{
struct request_header __header;
@ -3089,6 +3100,7 @@ enum request
REQ_free_console,
REQ_get_console_renderer_events,
REQ_open_console,
REQ_get_console_wait_event,
REQ_get_console_mode,
REQ_set_console_mode,
REQ_set_console_input_info,
@ -3270,6 +3282,7 @@ union generic_request
struct free_console_request free_console_request;
struct get_console_renderer_events_request get_console_renderer_events_request;
struct open_console_request open_console_request;
struct get_console_wait_event_request get_console_wait_event_request;
struct get_console_mode_request get_console_mode_request;
struct set_console_mode_request set_console_mode_request;
struct set_console_input_info_request set_console_input_info_request;
@ -3449,6 +3462,7 @@ union generic_reply
struct free_console_reply free_console_reply;
struct get_console_renderer_events_reply get_console_renderer_events_reply;
struct open_console_reply open_console_reply;
struct get_console_wait_event_reply get_console_wait_event_reply;
struct get_console_mode_reply get_console_mode_reply;
struct set_console_mode_reply set_console_mode_reply;
struct set_console_input_info_reply set_console_input_info_reply;
@ -3569,6 +3583,6 @@ union generic_reply
struct get_next_hook_reply get_next_hook_reply;
};
#define SERVER_PROTOCOL_VERSION 109
#define SERVER_PROTOCOL_VERSION 110
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View File

@ -535,6 +535,7 @@ static struct inner_data* WINECON_Init(HINSTANCE hInst, DWORD pid, LPCWSTR appna
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 @@ static struct inner_data* WINECON_Init(HINSTANCE hInst, DWORD pid, LPCWSTR appna
/* 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 @@ static struct inner_data* WINECON_Init(HINSTANCE hInst, DWORD pid, LPCWSTR appna
*/
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;

View File

@ -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 @@ BOOL WINAPI CloseHandle( HANDLE handle )
(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;
@ -101,8 +105,22 @@ BOOL WINAPI DuplicateHandle( HANDLE source_process, HANDLE source,
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;
}

View File

@ -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);
@ -328,19 +329,31 @@ static BOOL process_init( char *argv[] )
/* 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)
if (info_size == 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)
/* 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 (!process_pmts.hStdInput)
process_pmts.hStdInput = INVALID_HANDLE_VALUE;
else if (VerifyConsoleIoHandle(console_handle_map(process_pmts.hStdInput)))
process_pmts.hStdInput = console_handle_map(process_pmts.hStdInput);
if (!process_pmts.hStdOutput)
process_pmts.hStdOutput = INVALID_HANDLE_VALUE;
else if (VerifyConsoleIoHandle(console_handle_map(process_pmts.hStdOutput)))
process_pmts.hStdOutput = console_handle_map(process_pmts.hStdOutput);
if (!process_pmts.hStdError)
process_pmts.hStdError = INVALID_HANDLE_VALUE;
else 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();
@ -951,6 +964,20 @@ static BOOL create_process( HANDLE hFile, LPCSTR filename, LPSTR cmd_line, LPCST
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

View File

@ -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 @@ DWORD WINAPI WaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
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 @@ DWORD WINAPI WaitForMultipleObjectsEx( DWORD count, const HANDLE *handles,
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? */

View File

@ -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 @@ static struct console_input_events *create_console_input_events(void)
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 @@ static struct object *create_console_input( struct thread* renderer )
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 @@ void inherit_console(struct thread *parent_thread, struct process *process, obj_
}
}
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 @@ static struct console_input* console_input_get( obj_handle_t handle, unsigned ac
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 @@ static void console_input_destroy( struct object *obj )
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 @@ DECL_HANDLER(alloc_console)
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 @@ DECL_HANDLER(alloc_console)
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,35 @@ DECL_HANDLER(send_console_signal)
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 );
}

View File

@ -42,12 +42,12 @@ struct console_input
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 */

View File

@ -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 @@ DECL_HANDLER(get_handle_fd)
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 */

View File

@ -221,40 +221,11 @@ static int set_process_console( struct process *process, struct thread *parent_t
}
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 = 0;
/* some handles above may have been invalid; this is not an error */
if (get_error() == STATUS_INVALID_HANDLE) clear_error();
return 1;

View File

@ -627,7 +627,6 @@ enum fd_type
{
FD_TYPE_INVALID,
FD_TYPE_DEFAULT,
FD_TYPE_CONSOLE,
FD_TYPE_SOCKET,
FD_TYPE_SMB
};
@ -776,6 +775,7 @@ enum fd_type
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 @@ struct console_renderer_event
@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 */

View File

@ -159,6 +159,7 @@ DECL_HANDLER(alloc_console);
DECL_HANDLER(free_console);
DECL_HANDLER(get_console_renderer_events);
DECL_HANDLER(open_console);
DECL_HANDLER(get_console_wait_event);
DECL_HANDLER(get_console_mode);
DECL_HANDLER(set_console_mode);
DECL_HANDLER(set_console_input_info);
@ -339,6 +340,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(req_handler)req_free_console,
(req_handler)req_get_console_renderer_events,
(req_handler)req_open_console,
(req_handler)req_get_console_wait_event,
(req_handler)req_get_console_mode,
(req_handler)req_set_console_mode,
(req_handler)req_set_console_input_info,

View File

@ -997,7 +997,8 @@ static void dump_alloc_console_request( const struct alloc_console_request *req
{
fprintf( stderr, " access=%08x,", req->access );
fprintf( stderr, " inherit=%d,", req->inherit );
fprintf( stderr, " pid=%04x", req->pid );
fprintf( stderr, " pid=%04x,", req->pid );
fprintf( stderr, " wait_event=%p", req->wait_event );
}
static void dump_alloc_console_reply( const struct alloc_console_reply *req )
@ -1034,6 +1035,15 @@ static void dump_open_console_reply( const struct open_console_reply *req )
fprintf( stderr, " handle=%p", req->handle );
}
static void dump_get_console_wait_event_request( const struct get_console_wait_event_request *req )
{
}
static void dump_get_console_wait_event_reply( const struct get_console_wait_event_reply *req )
{
fprintf( stderr, " handle=%p", req->handle );
}
static void dump_get_console_mode_request( const struct get_console_mode_request *req )
{
fprintf( stderr, " handle=%p", req->handle );
@ -2506,6 +2516,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_free_console_request,
(dump_func)dump_get_console_renderer_events_request,
(dump_func)dump_open_console_request,
(dump_func)dump_get_console_wait_event_request,
(dump_func)dump_get_console_mode_request,
(dump_func)dump_set_console_mode_request,
(dump_func)dump_set_console_input_info_request,
@ -2683,6 +2694,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)0,
(dump_func)dump_get_console_renderer_events_reply,
(dump_func)dump_open_console_reply,
(dump_func)dump_get_console_wait_event_reply,
(dump_func)dump_get_console_mode_reply,
(dump_func)0,
(dump_func)0,
@ -2860,6 +2872,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"free_console",
"get_console_renderer_events",
"open_console",
"get_console_wait_event",
"get_console_mode",
"set_console_mode",
"set_console_input_info",