|  | /* | 
|  | * Win32 kernel functions | 
|  | * | 
|  | * Copyright 1995 Martin von Loewis and Cameron Heide | 
|  | * Copyright 1997 Karl Garrison | 
|  | * Copyright 1998 John Richardson | 
|  | * Copyright 1998 Marcus Meissner | 
|  | */ | 
|  |  | 
|  | /* FIXME: | 
|  | * - Completely lacks SCREENBUFFER interface. | 
|  | * - No abstraction for something other than xterm. | 
|  | * - Output sometimes is buffered (We switched off buffering by ~ICANON ?) | 
|  | */ | 
|  | /* Reference applications: | 
|  | * -  IDA (interactive disassembler) full version 3.75. Works. | 
|  | * -  LYNX/W32. Works mostly, some keys crash it. | 
|  | */ | 
|  |  | 
|  | #include "config.h" | 
|  |  | 
|  | #include <stdlib.h> | 
|  | #include <stdio.h> | 
|  | #include <unistd.h> | 
|  | #include <termios.h> | 
|  | #include <string.h> | 
|  | #include <sys/ioctl.h> | 
|  | #include <sys/types.h> | 
|  | #include <sys/time.h> | 
|  | #include <fcntl.h> | 
|  | #include <errno.h> | 
|  | #ifdef HAVE_SYS_ERRNO_H | 
|  | #include <sys/errno.h> | 
|  | #endif | 
|  | #include <signal.h> | 
|  | #include <assert.h> | 
|  |  | 
|  | #include "windef.h" | 
|  | #include "winbase.h" | 
|  | #include "winnls.h" | 
|  | #include "wingdi.h" | 
|  | #include "wine/winuser16.h" | 
|  | #include "wine/keyboard16.h" | 
|  | #include "thread.h" | 
|  | #include "winerror.h" | 
|  | #include "wincon.h" | 
|  | #include "heap.h" | 
|  | #include "wine/server.h" | 
|  | #include "debugtools.h" | 
|  |  | 
|  | DEFAULT_DEBUG_CHANNEL(console); | 
|  |  | 
|  | /* Ascii -> VK, generated by calling VkKeyScanA(i) */ | 
|  | static int vkkeyscan_table[256] = { | 
|  | 0,0,0,0,0,0,0,0,8,9,0,0,0,13,0,0,0,0,0,19,145,556,0,0,0,0,0,27,0,0,0, | 
|  | 0,32,305,478,307,308,309,311,222,313,304,312,443,188,189,190,191,48, | 
|  | 49,50,51,52,53,54,55,56,57,442,186,444,187,446,447,306,321,322,323, | 
|  | 324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340, | 
|  | 341,342,343,344,345,346,219,220,221,310,445,192,65,66,67,68,69,70,71, | 
|  | 72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,475,476,477, | 
|  | 448,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | 
|  | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | 
|  | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | 
|  | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,400,0,0,0,0,0,0 | 
|  | }; | 
|  |  | 
|  | static int mapvkey_0[256]={ | 
|  | 0,0,0,0,0,0,0,0,14,15,0,0,0,28,0,0,42,29,56,69,58,0,0,0,0,0,0,1,0,0, | 
|  | 0,0,57,73,81,79,71,75,72,77,80,0,0,0,55,82,83,0,11,2,3,4,5,6,7,8,9, | 
|  | 10,0,0,0,0,0,0,0,30,48,46,32,18,33,34,35,23,36,37,38,50,49,24,25,16, | 
|  | 19,31,20,22,47,17,45,21,44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,55,78,0,74, | 
|  | 0,53,59,60,61,62,63,64,65,66,67,68,87,88,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | 
|  | 0,0,0,0,0,0,69,70,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | 
|  | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,39,13,51,12,52,53,41,0,0,0,0,0,0,0,0,0, | 
|  | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,43,27,40,76,96,0,0,0,0,0,0,0,0, | 
|  | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 | 
|  | }; | 
|  |  | 
|  | static int mapvkey_1[256]={ | 
|  | 0,27,49,50,51,52,53,54,55,56,57,48,189,187,8,9,81,87,69,82,84,89,85, | 
|  | 73,79,80,219,221,13,17,65,83,68,70,71,72,74,75,76,186,222,192,16,220, | 
|  | 90,88,67,86,66,78,77,188,190,191,16,106,18,32,20,112,113,114,115,116, | 
|  | 117,118,119,120,121,144,145,36,38,33,109,37,223,39,107,35,40,34,45, | 
|  | 46,0,0,0,122,123,0,0,0,0,0,0,0,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | 
|  | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | 
|  | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | 
|  | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | 
|  | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | 
|  | 0,0,0,0,0,0,0 | 
|  | }; | 
|  |  | 
|  | /* FIXME:  Should be in an internal header file.  OK, so which one? | 
|  | Used by CONSOLE_make_complex. */ | 
|  | extern int wine_openpty(int *master, int *slave, char *name, | 
|  | struct termios *term, struct winsize *winsize); | 
|  |  | 
|  | /**************************************************************************** | 
|  | *		CONSOLE_GetPid | 
|  | */ | 
|  | static int CONSOLE_GetPid( HANDLE handle ) | 
|  | { | 
|  | int ret = 0; | 
|  | SERVER_START_REQ( get_console_info ) | 
|  | { | 
|  | req->handle = handle; | 
|  | if (!SERVER_CALL_ERR()) ret = req->pid; | 
|  | } | 
|  | SERVER_END_REQ; | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | /**************************************************************************** | 
|  | *		XTERM_string_to_IR			[internal] | 
|  | * | 
|  | * Transfers a string read from XTERM to INPUT_RECORDs and adds them to the | 
|  | * queue. Does translation of vt100 style function keys and xterm-mouse clicks. | 
|  | */ | 
|  | static void | 
|  | CONSOLE_string_to_IR( HANDLE hConsoleInput,unsigned char *buf,int len) { | 
|  | int			j,k; | 
|  | INPUT_RECORD	ir; | 
|  | DWORD		junk; | 
|  |  | 
|  | for (j=0;j<len;j++) { | 
|  | unsigned char inchar = buf[j]; | 
|  |  | 
|  | if (inchar!=27) { /* no escape -> 'normal' keyboard event */ | 
|  | ir.EventType = 1; /* Key_event */ | 
|  |  | 
|  | ir.Event.KeyEvent.bKeyDown		= 1; | 
|  | ir.Event.KeyEvent.wRepeatCount	= 0; | 
|  |  | 
|  | ir.Event.KeyEvent.dwControlKeyState	= 0; | 
|  | if (inchar & 0x80) { | 
|  | ir.Event.KeyEvent.dwControlKeyState|=LEFT_ALT_PRESSED; | 
|  | inchar &= ~0x80; | 
|  | } | 
|  | ir.Event.KeyEvent.wVirtualKeyCode = vkkeyscan_table[inchar]; | 
|  | if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0100) | 
|  | ir.Event.KeyEvent.dwControlKeyState|=SHIFT_PRESSED; | 
|  | if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0200) | 
|  | ir.Event.KeyEvent.dwControlKeyState|=LEFT_CTRL_PRESSED; | 
|  | if (ir.Event.KeyEvent.wVirtualKeyCode & 0x0400) | 
|  | ir.Event.KeyEvent.dwControlKeyState|=LEFT_ALT_PRESSED; | 
|  | ir.Event.KeyEvent.wVirtualScanCode = mapvkey_0[ | 
|  | ir.Event.KeyEvent.wVirtualKeyCode & 0x00ff | 
|  | ]; /* VirtualKeyCodes to ScanCode */ | 
|  | ir.Event.KeyEvent.uChar.AsciiChar = inchar; | 
|  |  | 
|  | if ((inchar==127)||(inchar=='\b')) { /* backspace */ | 
|  | ir.Event.KeyEvent.uChar.AsciiChar = '\b'; /* FIXME: hmm */ | 
|  | ir.Event.KeyEvent.wVirtualScanCode = 0x0e; | 
|  | ir.Event.KeyEvent.wVirtualKeyCode = VK_BACK; | 
|  | } else { | 
|  | if ((inchar=='\n')||(inchar=='\r')) { | 
|  | ir.Event.KeyEvent.uChar.AsciiChar	= '\r'; | 
|  | ir.Event.KeyEvent.wVirtualKeyCode	= VK_RETURN; | 
|  | ir.Event.KeyEvent.wVirtualScanCode	= 0x1c; | 
|  | ir.Event.KeyEvent.dwControlKeyState = 0; | 
|  | } else { | 
|  | if (inchar<' ') { | 
|  | /* FIXME: find good values for ^X */ | 
|  | ir.Event.KeyEvent.wVirtualKeyCode = 0xdead; | 
|  | ir.Event.KeyEvent.wVirtualScanCode = 0xbeef; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk )); | 
|  | ir.Event.KeyEvent.bKeyDown = 0; | 
|  | assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk )); | 
|  | continue; | 
|  | } | 
|  | /* inchar is ESC */ | 
|  | if ((j==len-1) || (buf[j+1]!='[')) {/* add ESCape on its own */ | 
|  | ir.EventType = 1; /* Key_event */ | 
|  | ir.Event.KeyEvent.bKeyDown		= 1; | 
|  | ir.Event.KeyEvent.wRepeatCount	= 0; | 
|  |  | 
|  | ir.Event.KeyEvent.wVirtualKeyCode	= VK_ESCAPE; | 
|  | ir.Event.KeyEvent.wVirtualScanCode	= mapvkey_0[ | 
|  | ir.Event.KeyEvent.wVirtualKeyCode | 
|  | ]; | 
|  | ir.Event.KeyEvent.dwControlKeyState = 0; | 
|  | ir.Event.KeyEvent.uChar.AsciiChar	= 27; | 
|  | assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk )); | 
|  | ir.Event.KeyEvent.bKeyDown = 0; | 
|  | assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk )); | 
|  | continue; | 
|  | } | 
|  | for (k=j;k<len;k++) { | 
|  | if (((buf[k]>='A') && (buf[k]<='Z')) || | 
|  | ((buf[k]>='a') && (buf[k]<='z')) || | 
|  | (buf[k]=='~') | 
|  | ) | 
|  | break; | 
|  | } | 
|  | if (k<len) { | 
|  | int	subid,scancode=0; | 
|  |  | 
|  | ir.EventType			= 1; /* Key_event */ | 
|  | ir.Event.KeyEvent.bKeyDown		= 1; | 
|  | ir.Event.KeyEvent.wRepeatCount	= 0; | 
|  | ir.Event.KeyEvent.dwControlKeyState	= 0; | 
|  |  | 
|  | ir.Event.KeyEvent.wVirtualKeyCode	= 0xad; /* FIXME */ | 
|  | ir.Event.KeyEvent.wVirtualScanCode	= 0xad; /* FIXME */ | 
|  | ir.Event.KeyEvent.uChar.AsciiChar	= 0; | 
|  |  | 
|  | switch (buf[k]) { | 
|  | case '~': | 
|  | sscanf(&buf[j+2],"%d",&subid); | 
|  | switch (subid) { | 
|  | case  2:/*INS */scancode = 0xe052;break; | 
|  | case  3:/*DEL */scancode = 0xe053;break; | 
|  | case  6:/*PGDW*/scancode = 0xe051;break; | 
|  | case  5:/*PGUP*/scancode = 0xe049;break; | 
|  | case 11:/*F1  */scancode = 0x003b;break; | 
|  | case 12:/*F2  */scancode = 0x003c;break; | 
|  | case 13:/*F3  */scancode = 0x003d;break; | 
|  | case 14:/*F4  */scancode = 0x003e;break; | 
|  | case 15:/*F5  */scancode = 0x003f;break; | 
|  | case 17:/*F6  */scancode = 0x0040;break; | 
|  | case 18:/*F7  */scancode = 0x0041;break; | 
|  | case 19:/*F8  */scancode = 0x0042;break; | 
|  | case 20:/*F9  */scancode = 0x0043;break; | 
|  | case 21:/*F10 */scancode = 0x0044;break; | 
|  | case 23:/*F11 */scancode = 0x00d9;break; | 
|  | case 24:/*F12 */scancode = 0x00da;break; | 
|  | /* FIXME: Shift-Fx */ | 
|  | default: | 
|  | FIXME("parse ESC[%d~\n",subid); | 
|  | break; | 
|  | } | 
|  | break; | 
|  | case 'A': /* Cursor Up    */scancode = 0xe048;break; | 
|  | case 'B': /* Cursor Down  */scancode = 0xe050;break; | 
|  | case 'D': /* Cursor Left  */scancode = 0xe04b;break; | 
|  | case 'C': /* Cursor Right */scancode = 0xe04d;break; | 
|  | case 'F': /* End          */scancode = 0xe04f;break; | 
|  | case 'H': /* Home         */scancode = 0xe047;break; | 
|  | case 'M': | 
|  | /* Mouse Button Press  (ESCM<button+'!'><x+'!'><y+'!'>) or | 
|  | *              Release (ESCM#<x+'!'><y+'!'> | 
|  | */ | 
|  | if (k<len-3) { | 
|  | ir.EventType			= MOUSE_EVENT; | 
|  | ir.Event.MouseEvent.dwMousePosition.X = buf[k+2]-'!'; | 
|  | ir.Event.MouseEvent.dwMousePosition.Y = buf[k+3]-'!'; | 
|  | if (buf[k+1]=='#') | 
|  | ir.Event.MouseEvent.dwButtonState = 0; | 
|  | else | 
|  | ir.Event.MouseEvent.dwButtonState = 1<<(buf[k+1]-' '); | 
|  | ir.Event.MouseEvent.dwEventFlags	  = 0; /* FIXME */ | 
|  | assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk)); | 
|  | j=k+3; | 
|  | } | 
|  | break; | 
|  | case 'c': | 
|  | j=k; | 
|  | break; | 
|  | } | 
|  | if (scancode) { | 
|  | ir.Event.KeyEvent.wVirtualScanCode = scancode; | 
|  | ir.Event.KeyEvent.wVirtualKeyCode  = mapvkey_1[scancode]; | 
|  | assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk )); | 
|  | ir.Event.KeyEvent.bKeyDown		= 0; | 
|  | assert(WriteConsoleInputA( hConsoleInput, &ir, 1, &junk )); | 
|  | j=k; | 
|  | continue; | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /**************************************************************************** | 
|  | * 		CONSOLE_get_input		(internal) | 
|  | * | 
|  | * Reads (nonblocking) as much input events as possible and stores them | 
|  | * in an internal queue. | 
|  | */ | 
|  | static void | 
|  | CONSOLE_get_input( HANDLE handle, BOOL blockwait ) | 
|  | { | 
|  | char	*buf = HeapAlloc(GetProcessHeap(),0,1); | 
|  | int		len = 0, escape_seen = 0; | 
|  |  | 
|  | while (1) | 
|  | { | 
|  | DWORD res; | 
|  | char inchar; | 
|  |  | 
|  | /* If we have at one time seen escape in this loop, we are | 
|  | * within an Escape sequence, so wait for a bit more input for the | 
|  | * rest of the loop. | 
|  | */ | 
|  | if (WaitForSingleObject( handle, escape_seen*10 )) break; | 
|  | if (!ReadFile( handle, &inchar, 1, &res, NULL )) break; | 
|  | if (!res) /* res 0 but readable means EOF? Hmm. */ | 
|  | break; | 
|  | buf = HeapReAlloc(GetProcessHeap(),0,buf,len+1); | 
|  | buf[len++]=inchar; | 
|  | if (inchar == 27) { | 
|  | if (len>1) { | 
|  | /* If we spot an ESC, we flush all up to it | 
|  | * since we can be sure that we have a complete | 
|  | * sequence. | 
|  | */ | 
|  | CONSOLE_string_to_IR(handle,buf,len-1); | 
|  | buf = HeapReAlloc(GetProcessHeap(),0,buf,1); | 
|  | buf[0] = 27; | 
|  | len = 1; | 
|  | } | 
|  | escape_seen = 1; | 
|  | } | 
|  | } | 
|  | CONSOLE_string_to_IR(handle,buf,len); | 
|  | HeapFree(GetProcessHeap(),0,buf); | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * read_console_input | 
|  | * | 
|  | * Helper function for ReadConsole, ReadConsoleInput and PeekConsoleInput | 
|  | */ | 
|  | static BOOL read_console_input( HANDLE handle, LPINPUT_RECORD buffer, DWORD count, | 
|  | LPDWORD read, BOOL flush ) | 
|  | { | 
|  | BOOL ret; | 
|  |  | 
|  | count = min( count, REQUEST_MAX_VAR_SIZE/sizeof(INPUT_RECORD) ); | 
|  |  | 
|  | SERVER_START_VAR_REQ( read_console_input, count*sizeof(INPUT_RECORD) ) | 
|  | { | 
|  | req->handle = handle; | 
|  | req->flush = flush; | 
|  | if ((ret = !SERVER_CALL_ERR())) | 
|  | { | 
|  | if (count) memcpy( buffer, server_data_ptr(req), server_data_size(req) ); | 
|  | if (read) *read = req->read; | 
|  | } | 
|  | } | 
|  | SERVER_END_VAR_REQ; | 
|  | return ret; | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * SetConsoleCtrlHandler [KERNEL32.@]  Adds function to calling process list | 
|  | * | 
|  | * PARAMS | 
|  | *    func [I] Address of handler function | 
|  | *    add  [I] Handler to add or remove | 
|  | * | 
|  | * RETURNS | 
|  | *    Success: TRUE | 
|  | *    Failure: FALSE | 
|  | * | 
|  | * CHANGED | 
|  | * James Sutherland (JamesSutherland@gmx.de) | 
|  | * Added global variables console_ignore_ctrl_c and handlers[] | 
|  | * Does not yet do any error checking, or set LastError if failed. | 
|  | * This doesn't yet matter, since these handlers are not yet called...! | 
|  | */ | 
|  | static unsigned int console_ignore_ctrl_c = 0; | 
|  | static PHANDLER_ROUTINE handlers[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; | 
|  | BOOL WINAPI SetConsoleCtrlHandler( PHANDLER_ROUTINE func, BOOL add ) | 
|  | { | 
|  | unsigned int alloc_loop = sizeof(handlers)/sizeof(PHANDLER_ROUTINE); | 
|  | unsigned int done = 0; | 
|  | FIXME("(%p,%i) - no error checking or testing yet\n", func, add); | 
|  | if (!func) | 
|  | { | 
|  | console_ignore_ctrl_c = add; | 
|  | return TRUE; | 
|  | } | 
|  | if (add) | 
|  | { | 
|  | for (;alloc_loop--;) | 
|  | if (!handlers[alloc_loop] && !done) | 
|  | { | 
|  | handlers[alloc_loop] = func; | 
|  | done++; | 
|  | } | 
|  | if (!done) | 
|  | FIXME("Out of space on CtrlHandler table\n"); | 
|  | return(done); | 
|  | } | 
|  | else | 
|  | { | 
|  | for (;alloc_loop--;) | 
|  | if (handlers[alloc_loop] == func && !done) | 
|  | { | 
|  | handlers[alloc_loop] = 0; | 
|  | done++; | 
|  | } | 
|  | if (!done) | 
|  | WARN("Attempt to remove non-installed CtrlHandler %p\n", | 
|  | func); | 
|  | return (done); | 
|  | } | 
|  | return (done); | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * GenerateConsoleCtrlEvent [KERNEL32.@] Simulate a CTRL-C or CTRL-BREAK | 
|  | * | 
|  | * PARAMS | 
|  | *    dwCtrlEvent        [I] Type of event | 
|  | *    dwProcessGroupID   [I] Process group ID to send event to | 
|  | * | 
|  | * NOTES | 
|  | *    Doesn't yet work...! | 
|  | * | 
|  | * RETURNS | 
|  | *    Success: True | 
|  | *    Failure: False (and *should* [but doesn't] set LastError) | 
|  | */ | 
|  | BOOL WINAPI GenerateConsoleCtrlEvent( DWORD dwCtrlEvent, | 
|  | DWORD dwProcessGroupID ) | 
|  | { | 
|  | if (dwCtrlEvent != CTRL_C_EVENT && dwCtrlEvent != CTRL_BREAK_EVENT) | 
|  | { | 
|  | ERR("invalid event %d for PGID %ld\n", | 
|  | (unsigned short)dwCtrlEvent, dwProcessGroupID ); | 
|  | return FALSE; | 
|  | } | 
|  | if (dwProcessGroupID == GetCurrentProcessId() ) | 
|  | { | 
|  | FIXME("Attempt to send event %d to self - stub\n", | 
|  | (unsigned short)dwCtrlEvent ); | 
|  | return FALSE; | 
|  | } | 
|  | FIXME("event %d to external PGID %ld - not implemented yet\n", | 
|  | (unsigned short)dwCtrlEvent, dwProcessGroupID ); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * CreateConsoleScreenBuffer [KERNEL32.@]  Creates a console screen buffer | 
|  | * | 
|  | * PARAMS | 
|  | *    dwDesiredAccess    [I] Access flag | 
|  | *    dwShareMode        [I] Buffer share mode | 
|  | *    sa                 [I] Security attributes | 
|  | *    dwFlags            [I] Type of buffer to create | 
|  | *    lpScreenBufferData [I] Reserved | 
|  | * | 
|  | * NOTES | 
|  | *    Should call SetLastError | 
|  | * | 
|  | * RETURNS | 
|  | *    Success: Handle to new console screen buffer | 
|  | *    Failure: INVALID_HANDLE_VALUE | 
|  | */ | 
|  | HANDLE WINAPI CreateConsoleScreenBuffer( DWORD dwDesiredAccess, | 
|  | DWORD dwShareMode, LPSECURITY_ATTRIBUTES sa, | 
|  | DWORD dwFlags, LPVOID lpScreenBufferData ) | 
|  | { | 
|  | FIXME("(%ld,%ld,%p,%ld,%p): stub\n",dwDesiredAccess, | 
|  | dwShareMode, sa, dwFlags, lpScreenBufferData); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return INVALID_HANDLE_VALUE; | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *           GetConsoleScreenBufferInfo   (KERNEL32.@) | 
|  | */ | 
|  | BOOL WINAPI GetConsoleScreenBufferInfo( HANDLE hConsoleOutput, | 
|  | LPCONSOLE_SCREEN_BUFFER_INFO csbi ) | 
|  | { | 
|  | csbi->dwSize.X = 80; | 
|  | csbi->dwSize.Y = 24; | 
|  | csbi->dwCursorPosition.X = 0; | 
|  | csbi->dwCursorPosition.Y = 0; | 
|  | csbi->wAttributes = 0; | 
|  | csbi->srWindow.Left	= 0; | 
|  | csbi->srWindow.Right	= 79; | 
|  | csbi->srWindow.Top	= 0; | 
|  | csbi->srWindow.Bottom	= 23; | 
|  | csbi->dwMaximumWindowSize.X = 80; | 
|  | csbi->dwMaximumWindowSize.Y = 24; | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * SetConsoleActiveScreenBuffer [KERNEL32.@]  Sets buffer to current console | 
|  | * | 
|  | * RETURNS | 
|  | *    Success: TRUE | 
|  | *    Failure: FALSE | 
|  | */ | 
|  | BOOL WINAPI SetConsoleActiveScreenBuffer( | 
|  | HANDLE hConsoleOutput) /* [in] Handle to console screen buffer */ | 
|  | { | 
|  | FIXME("(%x): stub\n", hConsoleOutput); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *            GetLargestConsoleWindowSize   (KERNEL32.@) | 
|  | * | 
|  | * NOTE | 
|  | *	This should return a COORD, but calling convention for returning | 
|  | *      structures is different between Windows and gcc on i386. | 
|  | * | 
|  | * VERSION: [i386] | 
|  | */ | 
|  | #ifdef __i386__ | 
|  | #undef GetLargestConsoleWindowSize | 
|  | DWORD WINAPI GetLargestConsoleWindowSize( HANDLE hConsoleOutput ) | 
|  | { | 
|  | COORD c; | 
|  | c.X = 80; | 
|  | c.Y = 24; | 
|  | return *(DWORD *)&c; | 
|  | } | 
|  | #endif /* defined(__i386__) */ | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *            GetLargestConsoleWindowSize   (KERNEL32.@) | 
|  | * | 
|  | * NOTE | 
|  | *	This should return a COORD, but calling convention for returning | 
|  | *      structures is different between Windows and gcc on i386. | 
|  | * | 
|  | * VERSION: [!i386] | 
|  | */ | 
|  | #ifndef __i386__ | 
|  | COORD WINAPI GetLargestConsoleWindowSize( HANDLE hConsoleOutput ) | 
|  | { | 
|  | COORD c; | 
|  | c.X = 80; | 
|  | c.Y = 24; | 
|  | return c; | 
|  | } | 
|  | #endif /* defined(__i386__) */ | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *            FreeConsole (KERNEL32.@) | 
|  | */ | 
|  | BOOL WINAPI FreeConsole(VOID) | 
|  | { | 
|  | BOOL ret; | 
|  | SERVER_START_REQ( free_console ) | 
|  | { | 
|  | ret = !SERVER_CALL_ERR(); | 
|  | } | 
|  | SERVER_END_REQ; | 
|  | return ret; | 
|  | } | 
|  |  | 
|  |  | 
|  | /************************************************************************* | 
|  | * 		CONSOLE_make_complex			[internal] | 
|  | * | 
|  | * Turns a CONSOLE kernel object into a complex one. | 
|  | * (switches from output/input using the terminal where WINE was started to | 
|  | * its own xterm). | 
|  | * | 
|  | * This makes simple commandline tools pipeable, while complex commandline | 
|  | * tools work without getting messed up by debug output. | 
|  | * | 
|  | * All other functions should work independently from this call. | 
|  | * | 
|  | * To test for complex console: pid == 0 -> simple, otherwise complex. | 
|  | */ | 
|  | static BOOL CONSOLE_make_complex(HANDLE handle) | 
|  | { | 
|  | struct termios term; | 
|  | char buf[256]; | 
|  | char c = '\0'; | 
|  | int i,xpid,master,slave; | 
|  |  | 
|  | if (CONSOLE_GetPid( handle )) return TRUE; /* already complex */ | 
|  |  | 
|  | MESSAGE("Console: Making console complex (creating an xterm)...\n"); | 
|  |  | 
|  | if (tcgetattr(0, &term) < 0) { | 
|  | /* ignore failure, or we can't run from a script */ | 
|  | } | 
|  | term.c_lflag = ~(ECHO|ICANON); | 
|  |  | 
|  | if (wine_openpty(&master, &slave, NULL, &term, NULL) < 0) | 
|  | return FALSE; | 
|  |  | 
|  | if ((xpid=fork()) == 0) { | 
|  | tcsetattr(slave, TCSADRAIN, &term); | 
|  | close( slave ); | 
|  | sprintf(buf, "-Sxx%d", master); | 
|  | /* "-fn vga" for VGA font. Harmless if vga is not present: | 
|  | *  xterm: unable to open font "vga", trying "fixed".... | 
|  | */ | 
|  | execlp("xterm", "xterm", buf, "-fn","vga",NULL); | 
|  | ERR("error creating AllocConsole xterm\n"); | 
|  | exit(1); | 
|  | } | 
|  | close( master ); | 
|  |  | 
|  | /* most xterms like to print their window ID when used with -S; | 
|  | * read it and continue before the user has a chance... | 
|  | */ | 
|  | for (i = 0; i < 10000; i++) | 
|  | { | 
|  | if (read( slave, &c, 1 ) == 1) | 
|  | { | 
|  | if (c == '\n') break; | 
|  | } | 
|  | else usleep(100); /* wait for xterm to be created */ | 
|  | } | 
|  | if (i == 10000) | 
|  | { | 
|  | ERR("can't read xterm WID\n"); | 
|  | close( slave ); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | wine_server_send_fd( slave ); | 
|  | SERVER_START_REQ( set_console_fd ) | 
|  | { | 
|  | req->handle = handle; | 
|  | req->fd_in  = slave; | 
|  | req->fd_out = slave; | 
|  | req->pid    = xpid; | 
|  | SERVER_CALL(); | 
|  | close( slave ); | 
|  | } | 
|  | SERVER_END_REQ; | 
|  |  | 
|  | /* enable mouseclicks */ | 
|  | strcpy( buf, "\033[?1002h" ); | 
|  | WriteFile(handle,buf,strlen(buf),NULL,NULL); | 
|  |  | 
|  | strcpy( buf, "\033]2;" ); | 
|  | if (GetConsoleTitleA( buf + 4, sizeof(buf) - 5 )) | 
|  | { | 
|  | strcat( buf, "\a" ); | 
|  | WriteFile(handle,buf,strlen(buf),NULL,NULL); | 
|  | } | 
|  | return TRUE; | 
|  |  | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *            AllocConsole (KERNEL32.@) | 
|  | * | 
|  | * creates an xterm with a pty to our program | 
|  | */ | 
|  | BOOL WINAPI AllocConsole(VOID) | 
|  | { | 
|  | BOOL ret; | 
|  | HANDLE hStderr; | 
|  | int handle_in, handle_out; | 
|  |  | 
|  | TRACE("()\n"); | 
|  |  | 
|  | SERVER_START_REQ( alloc_console ) | 
|  | { | 
|  | req->access  = GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE; | 
|  | req->inherit = FALSE; | 
|  | ret = !SERVER_CALL_ERR(); | 
|  | handle_in = req->handle_in; | 
|  | handle_out = req->handle_out; | 
|  | } | 
|  | SERVER_END_REQ; | 
|  | if (!ret) return FALSE; | 
|  |  | 
|  | if (!DuplicateHandle( GetCurrentProcess(), handle_out, GetCurrentProcess(), &hStderr, | 
|  | 0, TRUE, DUPLICATE_SAME_ACCESS )) | 
|  | { | 
|  | CloseHandle( handle_in ); | 
|  | CloseHandle( handle_out ); | 
|  | FreeConsole(); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | /* NT resets the STD_*_HANDLEs on console alloc */ | 
|  | SetStdHandle( STD_INPUT_HANDLE, handle_in ); | 
|  | SetStdHandle( STD_OUTPUT_HANDLE, handle_out ); | 
|  | SetStdHandle( STD_ERROR_HANDLE, hStderr ); | 
|  |  | 
|  | SetLastError(ERROR_SUCCESS); | 
|  | SetConsoleTitleA("Wine Console"); | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * GetConsoleCP [KERNEL32.@]  Returns the OEM code page for the console | 
|  | * | 
|  | * RETURNS | 
|  | *    Code page code | 
|  | */ | 
|  | UINT WINAPI GetConsoleCP(VOID) | 
|  | { | 
|  | return GetACP(); | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *            GetConsoleOutputCP   (KERNEL32.@) | 
|  | */ | 
|  | UINT WINAPI GetConsoleOutputCP(VOID) | 
|  | { | 
|  | return GetConsoleCP(); | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *            GetConsoleMode   (KERNEL32.@) | 
|  | */ | 
|  | BOOL WINAPI GetConsoleMode(HANDLE hcon,LPDWORD mode) | 
|  | { | 
|  | BOOL ret; | 
|  | SERVER_START_REQ( get_console_mode ) | 
|  | { | 
|  | req->handle = hcon; | 
|  | ret = !SERVER_CALL_ERR(); | 
|  | if (ret && mode) *mode = req->mode; | 
|  | } | 
|  | SERVER_END_REQ; | 
|  | return ret; | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * SetConsoleMode [KERNEL32.@]  Sets input mode of console's input buffer | 
|  | * | 
|  | * PARAMS | 
|  | *    hcon [I] Handle to console input or screen buffer | 
|  | *    mode [I] Input or output mode to set | 
|  | * | 
|  | * RETURNS | 
|  | *    Success: TRUE | 
|  | *    Failure: FALSE | 
|  | */ | 
|  | BOOL WINAPI SetConsoleMode( HANDLE hcon, DWORD mode ) | 
|  | { | 
|  | BOOL ret; | 
|  | SERVER_START_REQ( set_console_mode ) | 
|  | { | 
|  | req->handle = hcon; | 
|  | req->mode = mode; | 
|  | ret = !SERVER_CALL_ERR(); | 
|  | } | 
|  | SERVER_END_REQ; | 
|  | return ret; | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * SetConsoleOutputCP [KERNEL32.@]  Set the output codepage used by the console | 
|  | * | 
|  | * PARAMS | 
|  | *    cp [I] code page to set | 
|  | * | 
|  | * RETURNS | 
|  | *    Success: TRUE | 
|  | *    Failure: FALSE | 
|  | */ | 
|  | BOOL WINAPI SetConsoleOutputCP( UINT cp ) | 
|  | { | 
|  | FIXME("stub\n"); | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *            GetConsoleTitleA   (KERNEL32.@) | 
|  | */ | 
|  | DWORD WINAPI GetConsoleTitleA(LPSTR title,DWORD size) | 
|  | { | 
|  | DWORD ret = 0; | 
|  | HANDLE hcon; | 
|  |  | 
|  | if ((hcon = CreateFileA( "CONOUT$", GENERIC_READ, 0, NULL, | 
|  | OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE) | 
|  | return 0; | 
|  | SERVER_START_VAR_REQ( get_console_info, REQUEST_MAX_VAR_SIZE ) | 
|  | { | 
|  | req->handle = hcon; | 
|  | if (!SERVER_CALL_ERR()) | 
|  | { | 
|  | ret = server_data_size(req); | 
|  | size = min( size-1, ret ); | 
|  | memcpy( title, server_data_ptr(req), size ); | 
|  | title[size] = 0; | 
|  | } | 
|  | } | 
|  | SERVER_END_VAR_REQ; | 
|  | CloseHandle( hcon ); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * GetConsoleTitleW [KERNEL32.@]  Retrieves title string for console | 
|  | * | 
|  | * PARAMS | 
|  | *    title [O] Address of buffer for title | 
|  | *    size  [I] Size of buffer | 
|  | * | 
|  | * RETURNS | 
|  | *    Success: Length of string copied | 
|  | *    Failure: 0 | 
|  | */ | 
|  | DWORD WINAPI GetConsoleTitleW( LPWSTR title, DWORD size ) | 
|  | { | 
|  | char *tmp; | 
|  | DWORD ret; | 
|  |  | 
|  | if (!(tmp = HeapAlloc( GetProcessHeap(), 0, size*sizeof(WCHAR) ))) return 0; | 
|  | GetConsoleTitleA( tmp, size*sizeof(WCHAR) ); | 
|  | ret = MultiByteToWideChar( CP_ACP, 0, tmp, -1, title, size ); | 
|  | HeapFree( GetProcessHeap(), 0, tmp ); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *            WriteConsoleA   (KERNEL32.@) | 
|  | */ | 
|  | BOOL WINAPI WriteConsoleA( HANDLE hConsoleOutput, | 
|  | LPCVOID lpBuffer, | 
|  | DWORD nNumberOfCharsToWrite, | 
|  | LPDWORD lpNumberOfCharsWritten, | 
|  | LPVOID lpReserved ) | 
|  | { | 
|  | /* FIXME: should I check if this is a console handle? */ | 
|  | return WriteFile(hConsoleOutput, lpBuffer, nNumberOfCharsToWrite, | 
|  | lpNumberOfCharsWritten, NULL); | 
|  | } | 
|  |  | 
|  |  | 
|  | #define CADD(c) 							\ | 
|  | if (bufused==curbufsize-1)					\ | 
|  | buffer = HeapReAlloc(GetProcessHeap(),0,buffer,(curbufsize+=100));\ | 
|  | buffer[bufused++]=c; | 
|  | #define SADD(s) { char *x=s;while (*x) {CADD(*x);x++;}} | 
|  |  | 
|  | /*********************************************************************** | 
|  | *            WriteConsoleOutputA   (KERNEL32.@) | 
|  | */ | 
|  | BOOL WINAPI WriteConsoleOutputA( HANDLE hConsoleOutput, | 
|  | LPCHAR_INFO lpBuffer, | 
|  | COORD dwBufferSize, | 
|  | COORD dwBufferCoord, | 
|  | LPSMALL_RECT lpWriteRegion) | 
|  | { | 
|  | int i,j,off=0,lastattr=-1; | 
|  | int offbase; | 
|  | char	sbuf[20],*buffer=NULL; | 
|  | int		bufused=0,curbufsize = 100; | 
|  | DWORD	res; | 
|  | CONSOLE_SCREEN_BUFFER_INFO csbi; | 
|  | const int colormap[8] = { | 
|  | 0,4,2,6, | 
|  | 1,5,3,7, | 
|  | }; | 
|  | CONSOLE_make_complex(hConsoleOutput); | 
|  | buffer = HeapAlloc(GetProcessHeap(),0,curbufsize); | 
|  | offbase = (dwBufferCoord.Y - 1) * dwBufferSize.X + | 
|  | (dwBufferCoord.X - lpWriteRegion->Left); | 
|  |  | 
|  | TRACE("orig rect top = %d, bottom=%d, left=%d, right=%d\n", | 
|  | lpWriteRegion->Top, | 
|  | lpWriteRegion->Bottom, | 
|  | lpWriteRegion->Left, | 
|  | lpWriteRegion->Right | 
|  | ); | 
|  |  | 
|  | GetConsoleScreenBufferInfo(hConsoleOutput, &csbi); | 
|  | sprintf(sbuf,"%c7",27);SADD(sbuf); | 
|  |  | 
|  | /* Step 1. Make (Bottom,Right) offset of intersection with | 
|  | Screen Buffer                                              */ | 
|  | lpWriteRegion->Bottom = min(lpWriteRegion->Bottom, csbi.dwSize.Y-1) - | 
|  | lpWriteRegion->Top; | 
|  | lpWriteRegion->Right = min(lpWriteRegion->Right, csbi.dwSize.X-1) - | 
|  | lpWriteRegion->Left; | 
|  |  | 
|  | /* Step 2. If either offset is negative, then no action | 
|  | should be performed. (Implies that requested rectangle is | 
|  | outside the current screen buffer rectangle.)              */ | 
|  | if ((lpWriteRegion->Bottom < 0) || | 
|  | (lpWriteRegion->Right < 0)) { | 
|  | /* readjust (Bottom Right) for rectangle */ | 
|  | lpWriteRegion->Bottom += lpWriteRegion->Top; | 
|  | lpWriteRegion->Right += lpWriteRegion->Left; | 
|  |  | 
|  | TRACE("invisible rect top = %d, bottom=%d, left=%d, right=%d\n", | 
|  | lpWriteRegion->Top, | 
|  | lpWriteRegion->Bottom, | 
|  | lpWriteRegion->Left, | 
|  | lpWriteRegion->Right | 
|  | ); | 
|  |  | 
|  | HeapFree(GetProcessHeap(),0,buffer); | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /* Step 3. Intersect with source rectangle                    */ | 
|  | lpWriteRegion->Bottom = lpWriteRegion->Top - dwBufferCoord.Y + | 
|  | min(lpWriteRegion->Bottom + dwBufferCoord.Y, dwBufferSize.Y-1); | 
|  | lpWriteRegion->Right = lpWriteRegion->Left - dwBufferCoord.X + | 
|  | min(lpWriteRegion->Right + dwBufferCoord.X, dwBufferSize.X-1); | 
|  |  | 
|  | TRACE("clipped rect top = %d, bottom=%d, left=%d,right=%d\n", | 
|  | lpWriteRegion->Top, | 
|  | lpWriteRegion->Bottom, | 
|  | lpWriteRegion->Left, | 
|  | lpWriteRegion->Right | 
|  | ); | 
|  |  | 
|  | /* Validate above computations made sense, if not then issue | 
|  | error and fudge to single character rectangle                  */ | 
|  | if ((lpWriteRegion->Bottom < lpWriteRegion->Top) || | 
|  | (lpWriteRegion->Right < lpWriteRegion->Left)) { | 
|  | ERR("Invalid clipped rectangle top = %d, bottom=%d, left=%d,right=%d\n", | 
|  | lpWriteRegion->Top, | 
|  | lpWriteRegion->Bottom, | 
|  | lpWriteRegion->Left, | 
|  | lpWriteRegion->Right | 
|  | ); | 
|  | lpWriteRegion->Bottom = lpWriteRegion->Top; | 
|  | lpWriteRegion->Right = lpWriteRegion->Left; | 
|  | } | 
|  |  | 
|  | /* Now do the real processing and move the characters    */ | 
|  | for (i=lpWriteRegion->Top;i<=lpWriteRegion->Bottom;i++) { | 
|  | offbase += dwBufferSize.X; | 
|  | sprintf(sbuf,"%c[%d;%dH",27,i+1,lpWriteRegion->Left+1); | 
|  | SADD(sbuf); | 
|  | for (j=lpWriteRegion->Left;j<=lpWriteRegion->Right;j++) { | 
|  | off = j + offbase; | 
|  | if (lastattr!=lpBuffer[off].Attributes) { | 
|  | lastattr = lpBuffer[off].Attributes; | 
|  | sprintf(sbuf,"%c[0;%s3%d;4%dm", | 
|  | 27, | 
|  | (lastattr & FOREGROUND_INTENSITY)?"1;":"", | 
|  | colormap[lastattr&7], | 
|  | colormap[(lastattr&0x70)>>4] | 
|  | ); | 
|  | /* FIXME: BACKGROUND_INTENSITY */ | 
|  | SADD(sbuf); | 
|  | } | 
|  | CADD(lpBuffer[off].Char.AsciiChar); | 
|  | } | 
|  | } | 
|  | sprintf(sbuf,"%c[0m%c8",27,27);SADD(sbuf); | 
|  | WriteFile(hConsoleOutput,buffer,bufused,&res,NULL); | 
|  | HeapFree(GetProcessHeap(),0,buffer); | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *            WriteConsoleOutputW   (KERNEL32.@) | 
|  | */ | 
|  | BOOL WINAPI WriteConsoleOutputW( HANDLE hConsoleOutput, | 
|  | LPCHAR_INFO lpBuffer, | 
|  | COORD dwBufferSize, | 
|  | COORD dwBufferCoord, | 
|  | LPSMALL_RECT lpWriteRegion) | 
|  | { | 
|  | FIXME("(%d,%p,%dx%d,%dx%d,%p): stub\n", hConsoleOutput, lpBuffer, | 
|  | dwBufferSize.X,dwBufferSize.Y,dwBufferCoord.X,dwBufferCoord.Y,lpWriteRegion); | 
|  |  | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *            WriteConsoleW   (KERNEL32.@) | 
|  | */ | 
|  | BOOL WINAPI WriteConsoleW( HANDLE hConsoleOutput, | 
|  | LPCVOID lpBuffer, | 
|  | DWORD nNumberOfCharsToWrite, | 
|  | LPDWORD lpNumberOfCharsWritten, | 
|  | LPVOID lpReserved ) | 
|  | { | 
|  | BOOL ret; | 
|  | LPSTR xstring; | 
|  | DWORD n; | 
|  |  | 
|  | n = WideCharToMultiByte(CP_ACP,0,lpBuffer,nNumberOfCharsToWrite,NULL,0,NULL,NULL); | 
|  | xstring=HeapAlloc( GetProcessHeap(), 0, n ); | 
|  |  | 
|  | n = WideCharToMultiByte(CP_ACP,0,lpBuffer,nNumberOfCharsToWrite,xstring,n,NULL,NULL); | 
|  |  | 
|  | /* FIXME: should I check if this is a console handle? */ | 
|  | ret= WriteFile(hConsoleOutput, xstring, n, | 
|  | lpNumberOfCharsWritten, NULL); | 
|  | /* FIXME: lpNumberOfCharsWritten should be converted to numofchars in UNICODE */ | 
|  | HeapFree( GetProcessHeap(), 0, xstring ); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *            ReadConsoleA   (KERNEL32.@) | 
|  | */ | 
|  | BOOL WINAPI ReadConsoleA( HANDLE hConsoleInput, | 
|  | LPVOID lpBuffer, | 
|  | DWORD nNumberOfCharsToRead, | 
|  | LPDWORD lpNumberOfCharsRead, | 
|  | LPVOID lpReserved ) | 
|  | { | 
|  | DWORD	charsread = 0; | 
|  | LPSTR	xbuf = (LPSTR)lpBuffer; | 
|  |  | 
|  | TRACE("(%d,%p,%ld,%p,%p)\n", | 
|  | hConsoleInput,lpBuffer,nNumberOfCharsToRead, | 
|  | lpNumberOfCharsRead,lpReserved | 
|  | ); | 
|  |  | 
|  | CONSOLE_get_input(hConsoleInput,FALSE); | 
|  |  | 
|  | /* FIXME: should we read at least 1 char? The SDK does not say */ | 
|  | while (charsread<nNumberOfCharsToRead) | 
|  | { | 
|  | INPUT_RECORD ir; | 
|  | DWORD count; | 
|  | if (!read_console_input( hConsoleInput, &ir, 1, &count, TRUE )) return FALSE; | 
|  | if (!count) break; | 
|  | if (ir.EventType != KEY_EVENT) continue; | 
|  | if (!ir.Event.KeyEvent.bKeyDown) continue; | 
|  | *xbuf++ = ir.Event.KeyEvent.uChar.AsciiChar; | 
|  | charsread++; | 
|  | } | 
|  | if (lpNumberOfCharsRead) | 
|  | *lpNumberOfCharsRead = charsread; | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *            ReadConsoleW   (KERNEL32.@) | 
|  | */ | 
|  | BOOL WINAPI ReadConsoleW( HANDLE hConsoleInput, | 
|  | LPVOID lpBuffer, | 
|  | DWORD nNumberOfCharsToRead, | 
|  | LPDWORD lpNumberOfCharsRead, | 
|  | LPVOID lpReserved ) | 
|  | { | 
|  | BOOL ret; | 
|  | LPSTR buf = (LPSTR)HeapAlloc(GetProcessHeap(), 0, nNumberOfCharsToRead); | 
|  |  | 
|  | ret = ReadConsoleA( | 
|  | hConsoleInput, | 
|  | buf, | 
|  | nNumberOfCharsToRead, | 
|  | lpNumberOfCharsRead, | 
|  | lpReserved | 
|  | ); | 
|  | if (ret) | 
|  | MultiByteToWideChar( CP_ACP, 0, buf, -1, lpBuffer, nNumberOfCharsToRead ); | 
|  |  | 
|  | HeapFree( GetProcessHeap(), 0, buf ); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * ReadConsoleInputA [KERNEL32.@]  Reads data from a console | 
|  | * | 
|  | * PARAMS | 
|  | *    hConsoleInput        [I] Handle to console input buffer | 
|  | *    lpBuffer             [O] Address of buffer for read data | 
|  | *    nLength              [I] Number of records to read | 
|  | *    lpNumberOfEventsRead [O] Address of number of records read | 
|  | * | 
|  | * RETURNS | 
|  | *    Success: TRUE | 
|  | *    Failure: FALSE | 
|  | */ | 
|  | BOOL WINAPI ReadConsoleInputA(HANDLE hConsoleInput, LPINPUT_RECORD lpBuffer, | 
|  | DWORD nLength, LPDWORD lpNumberOfEventsRead) | 
|  | { | 
|  | if (!nLength) | 
|  | { | 
|  | if (lpNumberOfEventsRead) *lpNumberOfEventsRead = 0; | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /* loop until we get at least one event */ | 
|  | for (;;) | 
|  | { | 
|  | DWORD count; | 
|  | BOOL ret = read_console_input( hConsoleInput, lpBuffer, nLength, &count, TRUE ); | 
|  |  | 
|  | if (!ret) return FALSE; | 
|  | if (count) | 
|  | { | 
|  | if (lpNumberOfEventsRead) *lpNumberOfEventsRead = count; | 
|  | return TRUE; | 
|  | } | 
|  | CONSOLE_get_input(hConsoleInput,TRUE); | 
|  | /*WaitForSingleObject( hConsoleInput, INFINITE32 );*/ | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *            ReadConsoleInputW   (KERNEL32.@) | 
|  | */ | 
|  | BOOL WINAPI ReadConsoleInputW( HANDLE handle, LPINPUT_RECORD buffer, | 
|  | DWORD count, LPDWORD read ) | 
|  | { | 
|  | /* FIXME: Fix this if we get UNICODE input. */ | 
|  | return ReadConsoleInputA( handle, buffer, count, read ); | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *            FlushConsoleInputBuffer   (KERNEL32.@) | 
|  | */ | 
|  | BOOL WINAPI FlushConsoleInputBuffer( HANDLE handle ) | 
|  | { | 
|  | return read_console_input( handle, NULL, 0, NULL, TRUE ); | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *            PeekConsoleInputA   (KERNEL32.@) | 
|  | * | 
|  | * Gets 'count' first events (or less) from input queue. | 
|  | * | 
|  | * Does not need a complex console. | 
|  | */ | 
|  | BOOL WINAPI PeekConsoleInputA( HANDLE handle, LPINPUT_RECORD buffer, DWORD count, LPDWORD read ) | 
|  | { | 
|  | CONSOLE_get_input(handle,FALSE); | 
|  | if (!count) | 
|  | { | 
|  | if (read) *read = 0; | 
|  | return TRUE; | 
|  | } | 
|  | return read_console_input( handle, buffer, count, read, FALSE ); | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *            PeekConsoleInputW   (KERNEL32.@) | 
|  | */ | 
|  | BOOL WINAPI PeekConsoleInputW(HANDLE hConsoleInput, | 
|  | LPINPUT_RECORD pirBuffer, | 
|  | DWORD cInRecords, | 
|  | LPDWORD lpcRead) | 
|  | { | 
|  | /* FIXME: Hmm. Fix this if we get UNICODE input. */ | 
|  | return PeekConsoleInputA(hConsoleInput,pirBuffer,cInRecords,lpcRead); | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * WriteConsoleInputA [KERNEL32.@]  Write data to a console input buffer | 
|  | * | 
|  | */ | 
|  | BOOL WINAPI WriteConsoleInputA( HANDLE handle, INPUT_RECORD *buffer, | 
|  | DWORD count, LPDWORD written ) | 
|  | { | 
|  | BOOL ret = TRUE; | 
|  |  | 
|  | if (written) *written = 0; | 
|  | while (count && ret) | 
|  | { | 
|  | DWORD len = min( count, REQUEST_MAX_VAR_SIZE/sizeof(INPUT_RECORD) ); | 
|  | SERVER_START_VAR_REQ( write_console_input, len * sizeof(INPUT_RECORD) ) | 
|  | { | 
|  | req->handle = handle; | 
|  | memcpy( server_data_ptr(req), buffer, len * sizeof(INPUT_RECORD) ); | 
|  | if ((ret = !SERVER_CALL_ERR())) | 
|  | { | 
|  | if (written) *written += req->written; | 
|  | count -= len; | 
|  | buffer += len; | 
|  | } | 
|  | } | 
|  | SERVER_END_VAR_REQ; | 
|  | } | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | /****************************************************************************** | 
|  | * WriteConsoleInputW [KERNEL32.@]  Write data to a console input buffer | 
|  | * | 
|  | */ | 
|  | BOOL WINAPI WriteConsoleInputW( HANDLE handle, INPUT_RECORD *buffer, | 
|  | DWORD count, LPDWORD written ) | 
|  | { | 
|  | FIXME("(%d,%p,%ld,%p): stub!\n", handle, buffer, count, written); | 
|  |  | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  |  | 
|  | /*********************************************************************** | 
|  | *            SetConsoleTitleA   (KERNEL32.@) | 
|  | * | 
|  | * Sets the console title. | 
|  | * | 
|  | * We do not necessarily need to create a complex console for that, | 
|  | * but should remember the title and set it on creation of the latter. | 
|  | * (not fixed at this time). | 
|  | */ | 
|  | BOOL WINAPI SetConsoleTitleA(LPCSTR title) | 
|  | { | 
|  | size_t len = strlen(title); | 
|  | HANDLE hcon; | 
|  | DWORD written; | 
|  | BOOL ret; | 
|  |  | 
|  | if ((hcon = CreateFileA( "CONOUT$", GENERIC_READ|GENERIC_WRITE, 0, NULL, | 
|  | OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE) | 
|  | return FALSE; | 
|  |  | 
|  | len = min( len, REQUEST_MAX_VAR_SIZE ); | 
|  | SERVER_START_VAR_REQ( set_console_info, len ) | 
|  | { | 
|  | req->handle = hcon; | 
|  | req->mask = SET_CONSOLE_INFO_TITLE; | 
|  | memcpy( server_data_ptr(req), title, len ); | 
|  | ret = !SERVER_CALL_ERR(); | 
|  | } | 
|  | SERVER_END_VAR_REQ; | 
|  |  | 
|  | if (ret && CONSOLE_GetPid( hcon )) | 
|  | { | 
|  | /* only set title for complex console (own xterm) */ | 
|  | WriteFile( hcon, "\033]2;", 4, &written, NULL ); | 
|  | WriteFile( hcon, title, strlen(title), &written, NULL ); | 
|  | WriteFile( hcon, "\a", 1, &written, NULL ); | 
|  | } | 
|  | CloseHandle( hcon ); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * SetConsoleTitleW [KERNEL32.@]  Sets title bar string for console | 
|  | * | 
|  | * PARAMS | 
|  | *    title [I] Address of new title | 
|  | * | 
|  | * NOTES | 
|  | *    This should not be calling the A version | 
|  | * | 
|  | * RETURNS | 
|  | *    Success: TRUE | 
|  | *    Failure: FALSE | 
|  | */ | 
|  | BOOL WINAPI SetConsoleTitleW( LPCWSTR title ) | 
|  | { | 
|  | BOOL ret; | 
|  |  | 
|  | LPSTR titleA = HEAP_strdupWtoA( GetProcessHeap(), 0, title ); | 
|  | ret = SetConsoleTitleA(titleA); | 
|  | HeapFree( GetProcessHeap(), 0, titleA ); | 
|  | return ret; | 
|  | } | 
|  |  | 
|  | /****************************************************************************** | 
|  | * SetConsoleCursorPosition [KERNEL32.@] | 
|  | * Sets the cursor position in console | 
|  | * | 
|  | * PARAMS | 
|  | *    hConsoleOutput   [I] Handle of console screen buffer | 
|  | *    dwCursorPosition [I] New cursor position coordinates | 
|  | * | 
|  | * RETURNS STD | 
|  | */ | 
|  | BOOL WINAPI SetConsoleCursorPosition( HANDLE hcon, COORD pos ) | 
|  | { | 
|  | char 	xbuf[20]; | 
|  | DWORD	xlen; | 
|  |  | 
|  | /* make console complex only if we change lines, not just in the line */ | 
|  | if (pos.Y) | 
|  | CONSOLE_make_complex(hcon); | 
|  |  | 
|  | TRACE("%d (%dx%d)\n", hcon, pos.X , pos.Y ); | 
|  | /* x are columns, y rows */ | 
|  | if (pos.Y) | 
|  | /* full screen cursor absolute positioning */ | 
|  | sprintf(xbuf,"%c[%d;%dH", 0x1B, pos.Y+1, pos.X+1); | 
|  | else | 
|  | /* relative cursor positioning in line (\r to go to 0) */ | 
|  | sprintf(xbuf,"\r%c[%dC", 0x1B, pos.X); | 
|  | /* FIXME: store internal if we start using own console buffers */ | 
|  | WriteFile(hcon,xbuf,strlen(xbuf),&xlen,NULL); | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *            GetNumberOfConsoleInputEvents   (KERNEL32.@) | 
|  | */ | 
|  | BOOL WINAPI GetNumberOfConsoleInputEvents(HANDLE hcon,LPDWORD nrofevents) | 
|  | { | 
|  | CONSOLE_get_input (hcon, FALSE); | 
|  |  | 
|  | return read_console_input( hcon, NULL, 0, nrofevents, FALSE ); | 
|  | } | 
|  |  | 
|  | /*********************************************************************** | 
|  | *            GetNumberOfConsoleMouseButtons   (KERNEL32.@) | 
|  | */ | 
|  | BOOL WINAPI GetNumberOfConsoleMouseButtons(LPDWORD nrofbuttons) | 
|  | { | 
|  | FIXME("(%p): stub\n", nrofbuttons); | 
|  | *nrofbuttons = 2; | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /****************************************************************************** | 
|  | * GetConsoleCursorInfo [KERNEL32.@]  Gets size and visibility of console | 
|  | * | 
|  | * PARAMS | 
|  | *    hcon  [I] Handle to console screen buffer | 
|  | *    cinfo [O] Address of cursor information | 
|  | * | 
|  | * RETURNS | 
|  | *    Success: TRUE | 
|  | *    Failure: FALSE | 
|  | */ | 
|  | BOOL WINAPI GetConsoleCursorInfo( HANDLE hcon, LPCONSOLE_CURSOR_INFO cinfo ) | 
|  | { | 
|  | BOOL ret; | 
|  |  | 
|  | SERVER_START_REQ( get_console_info ) | 
|  | { | 
|  | req->handle = hcon; | 
|  | ret = !SERVER_CALL_ERR(); | 
|  | if (ret && cinfo) | 
|  | { | 
|  | cinfo->dwSize = req->cursor_size; | 
|  | cinfo->bVisible = req->cursor_visible; | 
|  | } | 
|  | } | 
|  | SERVER_END_REQ; | 
|  | return ret; | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * SetConsoleCursorInfo [KERNEL32.@]  Sets size and visibility of cursor | 
|  | * | 
|  | * RETURNS | 
|  | *    Success: TRUE | 
|  | *    Failure: FALSE | 
|  | */ | 
|  | BOOL WINAPI SetConsoleCursorInfo( | 
|  | HANDLE hcon,                /* [in] Handle to console screen buffer */ | 
|  | LPCONSOLE_CURSOR_INFO cinfo)  /* [in] Address of cursor information */ | 
|  | { | 
|  | char	buf[8]; | 
|  | DWORD	xlen; | 
|  | BOOL ret; | 
|  |  | 
|  | CONSOLE_make_complex(hcon); | 
|  | sprintf(buf,"\033[?25%c",cinfo->bVisible?'h':'l'); | 
|  | WriteFile(hcon,buf,strlen(buf),&xlen,NULL); | 
|  |  | 
|  | SERVER_START_REQ( set_console_info ) | 
|  | { | 
|  | req->handle         = hcon; | 
|  | req->cursor_size    = cinfo->dwSize; | 
|  | req->cursor_visible = cinfo->bVisible; | 
|  | req->mask           = SET_CONSOLE_INFO_CURSOR; | 
|  | ret = !SERVER_CALL_ERR(); | 
|  | } | 
|  | SERVER_END_REQ; | 
|  | return ret; | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * SetConsoleWindowInfo [KERNEL32.@]  Sets size and position of console | 
|  | * | 
|  | * RETURNS | 
|  | *    Success: TRUE | 
|  | *    Failure: FALSE | 
|  | */ | 
|  | BOOL WINAPI SetConsoleWindowInfo( | 
|  | HANDLE hcon,       /* [in] Handle to console screen buffer */ | 
|  | BOOL bAbsolute,    /* [in] Coordinate type flag */ | 
|  | LPSMALL_RECT window) /* [in] Address of new window rectangle */ | 
|  | { | 
|  | FIXME("(%x,%d,%p): stub\n", hcon, bAbsolute, window); | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * SetConsoleTextAttribute [KERNEL32.@]  Sets colors for text | 
|  | * | 
|  | * Sets the foreground and background color attributes of characters | 
|  | * written to the screen buffer. | 
|  | * | 
|  | * RETURNS | 
|  | *    Success: TRUE | 
|  | *    Failure: FALSE | 
|  | */ | 
|  | BOOL WINAPI SetConsoleTextAttribute(HANDLE hConsoleOutput,WORD wAttr) | 
|  | { | 
|  | const int colormap[8] = { | 
|  | 0,4,2,6, | 
|  | 1,5,3,7, | 
|  | }; | 
|  | DWORD xlen; | 
|  | char buffer[20]; | 
|  |  | 
|  | TRACE("(%d,%d)\n",hConsoleOutput,wAttr); | 
|  | sprintf(buffer,"%c[0;%s3%d;4%dm", | 
|  | 27, | 
|  | (wAttr & FOREGROUND_INTENSITY)?"1;":"", | 
|  | colormap[wAttr&7], | 
|  | colormap[(wAttr&0x70)>>4] | 
|  | ); | 
|  | WriteFile(hConsoleOutput,buffer,strlen(buffer),&xlen,NULL); | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * SetConsoleScreenBufferSize [KERNEL32.@]  Changes size of console | 
|  | * | 
|  | * PARAMS | 
|  | *    hConsoleOutput [I] Handle to console screen buffer | 
|  | *    dwSize         [I] New size in character rows and cols | 
|  | * | 
|  | * RETURNS | 
|  | *    Success: TRUE | 
|  | *    Failure: FALSE | 
|  | */ | 
|  | BOOL WINAPI SetConsoleScreenBufferSize( HANDLE hConsoleOutput, | 
|  | COORD dwSize ) | 
|  | { | 
|  | FIXME("(%d,%dx%d): stub\n",hConsoleOutput,dwSize.X,dwSize.Y); | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * FillConsoleOutputCharacterA [KERNEL32.@] | 
|  | * | 
|  | * PARAMS | 
|  | *    hConsoleOutput    [I] Handle to screen buffer | 
|  | *    cCharacter        [I] Character to write | 
|  | *    nLength           [I] Number of cells to write to | 
|  | *    dwCoord           [I] Coords of first cell | 
|  | *    lpNumCharsWritten [O] Pointer to number of cells written | 
|  | * | 
|  | * RETURNS | 
|  | *    Success: TRUE | 
|  | *    Failure: FALSE | 
|  | */ | 
|  | BOOL WINAPI FillConsoleOutputCharacterA( | 
|  | HANDLE hConsoleOutput, | 
|  | BYTE cCharacter, | 
|  | DWORD nLength, | 
|  | COORD dwCoord, | 
|  | LPDWORD lpNumCharsWritten) | 
|  | { | 
|  | DWORD 	count; | 
|  | DWORD	xlen; | 
|  |  | 
|  | SetConsoleCursorPosition(hConsoleOutput,dwCoord); | 
|  | for(count=0;count<nLength;count++) | 
|  | WriteFile(hConsoleOutput,&cCharacter,1,&xlen,NULL); | 
|  | *lpNumCharsWritten = nLength; | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * FillConsoleOutputCharacterW [KERNEL32.@]  Writes characters to console | 
|  | * | 
|  | * PARAMS | 
|  | *    hConsoleOutput    [I] Handle to screen buffer | 
|  | *    cCharacter        [I] Character to write | 
|  | *    nLength           [I] Number of cells to write to | 
|  | *    dwCoord           [I] Coords of first cell | 
|  | *    lpNumCharsWritten [O] Pointer to number of cells written | 
|  | * | 
|  | * RETURNS | 
|  | *    Success: TRUE | 
|  | *    Failure: FALSE | 
|  | */ | 
|  | BOOL WINAPI FillConsoleOutputCharacterW(HANDLE hConsoleOutput, | 
|  | WCHAR cCharacter, | 
|  | DWORD nLength, | 
|  | COORD dwCoord, | 
|  | LPDWORD lpNumCharsWritten) | 
|  | { | 
|  | DWORD	count; | 
|  | DWORD	xlen; | 
|  |  | 
|  | SetConsoleCursorPosition(hConsoleOutput,dwCoord); | 
|  | /* FIXME: not quite correct ... but the lower part of UNICODE char comes | 
|  | * first | 
|  | */ | 
|  | for(count=0;count<nLength;count++) | 
|  | WriteFile(hConsoleOutput,&cCharacter,1,&xlen,NULL); | 
|  | *lpNumCharsWritten = nLength; | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * FillConsoleOutputAttribute [KERNEL32.@]  Sets attributes for console | 
|  | * | 
|  | * PARAMS | 
|  | *    hConsoleOutput    [I] Handle to screen buffer | 
|  | *    wAttribute        [I] Color attribute to write | 
|  | *    nLength           [I] Number of cells to write to | 
|  | *    dwCoord           [I] Coords of first cell | 
|  | *    lpNumAttrsWritten [O] Pointer to number of cells written | 
|  | * | 
|  | * RETURNS | 
|  | *    Success: TRUE | 
|  | *    Failure: FALSE | 
|  | */ | 
|  | BOOL WINAPI FillConsoleOutputAttribute( HANDLE hConsoleOutput, | 
|  | WORD wAttribute, DWORD nLength, COORD dwCoord, | 
|  | LPDWORD lpNumAttrsWritten) | 
|  | { | 
|  | FIXME("(%d,%d,%ld,%dx%d,%p): stub\n", hConsoleOutput, | 
|  | wAttribute,nLength,dwCoord.X,dwCoord.Y,lpNumAttrsWritten); | 
|  | *lpNumAttrsWritten = nLength; | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /****************************************************************************** | 
|  | * ReadConsoleOutputCharacterA [KERNEL32.@] | 
|  | * | 
|  | * BUGS | 
|  | *   Unimplemented | 
|  | */ | 
|  | BOOL WINAPI ReadConsoleOutputCharacterA(HANDLE hConsoleOutput, | 
|  | LPSTR lpstr, DWORD dword, COORD coord, LPDWORD lpdword) | 
|  | { | 
|  | FIXME("(%d,%p,%ld,%dx%d,%p): stub\n", hConsoleOutput,lpstr, | 
|  | dword,coord.X,coord.Y,lpdword); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | /****************************************************************************** | 
|  | * ReadConsoleOutputCharacterW [KERNEL32.@] | 
|  | * | 
|  | * BUGS | 
|  | *   Unimplemented | 
|  | */ | 
|  | BOOL WINAPI ReadConsoleOutputCharacterW(HANDLE hConsoleOutput, | 
|  | LPWSTR lpstr, DWORD dword, COORD coord, LPDWORD lpdword) | 
|  | { | 
|  | FIXME("(%d,%p,%ld,%dx%d,%p): stub\n", hConsoleOutput,lpstr, | 
|  | dword,coord.X,coord.Y,lpdword); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  |  | 
|  | /****************************************************************************** | 
|  | * ScrollConsoleScreenBufferA [KERNEL32.@] | 
|  | * | 
|  | * BUGS | 
|  | *   Unimplemented | 
|  | */ | 
|  | BOOL WINAPI ScrollConsoleScreenBufferA( HANDLE hConsoleOutput, | 
|  | LPSMALL_RECT lpScrollRect, LPSMALL_RECT lpClipRect, | 
|  | COORD dwDestOrigin, LPCHAR_INFO lpFill) | 
|  | { | 
|  | FIXME("(%d,%p,%p,%dx%d,%p): stub\n", hConsoleOutput,lpScrollRect, | 
|  | lpClipRect,dwDestOrigin.X,dwDestOrigin.Y,lpFill); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | /****************************************************************************** | 
|  | * ScrollConsoleScreenBufferW [KERNEL32.@] | 
|  | * | 
|  | * BUGS | 
|  | *   Unimplemented | 
|  | */ | 
|  | BOOL WINAPI ScrollConsoleScreenBufferW( HANDLE hConsoleOutput, | 
|  | LPSMALL_RECT lpScrollRect, LPSMALL_RECT lpClipRect, | 
|  | COORD dwDestOrigin, LPCHAR_INFO lpFill) | 
|  | { | 
|  | FIXME("(%d,%p,%p,%dx%d,%p): stub\n", hConsoleOutput,lpScrollRect, | 
|  | lpClipRect,dwDestOrigin.X,dwDestOrigin.Y,lpFill); | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | /****************************************************************************** | 
|  | *  ReadConsoleOutputA [KERNEL32.@] | 
|  | * | 
|  | * BUGS | 
|  | *   Unimplemented | 
|  | */ | 
|  | BOOL WINAPI ReadConsoleOutputA( HANDLE hConsoleOutput, | 
|  | LPCHAR_INFO lpBuffer, | 
|  | COORD dwBufferSize, | 
|  | COORD dwBufferCoord, | 
|  | LPSMALL_RECT lpReadRegion ) | 
|  | { | 
|  | FIXME("(%d,%p,%dx%d,%dx%d,%p): stub\n", hConsoleOutput, lpBuffer, | 
|  | dwBufferSize.X, dwBufferSize.Y, dwBufferSize.X, dwBufferSize.Y, | 
|  | lpReadRegion); | 
|  |  | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | /****************************************************************************** | 
|  | *  ReadConsoleOutputW [KERNEL32.@] | 
|  | * | 
|  | * BUGS | 
|  | *   Unimplemented | 
|  | */ | 
|  | BOOL WINAPI ReadConsoleOutputW( HANDLE hConsoleOutput, | 
|  | LPCHAR_INFO lpBuffer, | 
|  | COORD dwBufferSize, | 
|  | COORD dwBufferCoord, | 
|  | LPSMALL_RECT lpReadRegion ) | 
|  | { | 
|  | FIXME("(%d,%p,%dx%d,%dx%d,%p): stub\n", hConsoleOutput, lpBuffer, | 
|  | dwBufferSize.X, dwBufferSize.Y, dwBufferSize.X, dwBufferSize.Y, | 
|  | lpReadRegion); | 
|  |  | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | /****************************************************************************** | 
|  | *  ReadConsoleOutputAttribute [KERNEL32.@] | 
|  | * | 
|  | * BUGS | 
|  | *   Unimplemented | 
|  | */ | 
|  | BOOL WINAPI ReadConsoleOutputAttribute( HANDLE hConsoleOutput, | 
|  | LPWORD lpAttribute, | 
|  | DWORD nLength, | 
|  | COORD dwReadCoord, | 
|  | LPDWORD lpNumberOfAttrsRead) | 
|  | { | 
|  | FIXME("(%d,%p,%ld,%dx%d,%p): stub\n", hConsoleOutput, lpAttribute, | 
|  | nLength, dwReadCoord.X, dwReadCoord.Y, lpNumberOfAttrsRead); | 
|  |  | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | /****************************************************************************** | 
|  | *  SetConsoleCP	 [KERNEL32.@] | 
|  | * | 
|  | * BUGS | 
|  | *   Unimplemented | 
|  | */ | 
|  | BOOL WINAPI SetConsoleCP( UINT cp ) | 
|  | { | 
|  | FIXME("(%d): stub\n", cp); | 
|  |  | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return FALSE; | 
|  | } | 
|  |  | 
|  | /****************************************************************************** | 
|  | *  SetConsoleInputExeNameW	 [KERNEL32.@] | 
|  | * | 
|  | * BUGS | 
|  | *   Unimplemented | 
|  | */ | 
|  | BOOL WINAPI SetConsoleInputExeNameW( LPCWSTR name ) | 
|  | { | 
|  | FIXME("(%s): stub!\n", debugstr_w(name)); | 
|  |  | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /****************************************************************************** | 
|  | *  SetConsoleInputExeNameA	 [KERNEL32.@] | 
|  | * | 
|  | * BUGS | 
|  | *   Unimplemented | 
|  | */ | 
|  | BOOL WINAPI SetConsoleInputExeNameA( LPCSTR name ) | 
|  | { | 
|  | FIXME("(%s): stub!\n", name); | 
|  |  | 
|  | SetLastError(ERROR_CALL_NOT_IMPLEMENTED); | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /****************************************************************************** | 
|  | * WriteConsoleOutputAttribute [KERNEL32.@]  Sets attributes for some cells in | 
|  | * 					     the console screen buffer | 
|  | * | 
|  | * PARAMS | 
|  | *    hConsoleOutput    [I] Handle to screen buffer | 
|  | *    lpAttribute       [I] Pointer to buffer with write attributes | 
|  | *    nLength           [I] Number of cells to write to | 
|  | *    dwCoord           [I] Coords of first cell | 
|  | *    lpNumAttrsWritten [O] Pointer to number of cells written | 
|  | * | 
|  | * RETURNS | 
|  | *    Success: TRUE | 
|  | *    Failure: FALSE | 
|  | * | 
|  | * BUGS | 
|  | *   Unimplemented | 
|  | */ | 
|  | BOOL WINAPI WriteConsoleOutputAttribute( HANDLE hConsoleOutput, | 
|  | CONST WORD *lpAttribute, DWORD nLength, COORD dwCoord, | 
|  | LPDWORD lpNumAttrsWritten) | 
|  | { | 
|  | FIXME("(%d,%p,%ld,%dx%d,%p): stub\n", hConsoleOutput, | 
|  | lpAttribute,nLength,dwCoord.X,dwCoord.Y,lpNumAttrsWritten); | 
|  | *lpNumAttrsWritten = nLength; | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /****************************************************************************** | 
|  | * WriteConsoleOutputCharacterA [KERNEL32.@]  Copies character to consecutive | 
|  | * 					      cells in the console screen buffer | 
|  | * | 
|  | * PARAMS | 
|  | *    hConsoleOutput    [I] Handle to screen buffer | 
|  | *    lpCharacter       [I] Pointer to buffer with chars to write | 
|  | *    nLength           [I] Number of cells to write to | 
|  | *    dwCoord           [I] Coords of first cell | 
|  | *    lpNumCharsWritten [O] Pointer to number of cells written | 
|  | * | 
|  | * BUGS | 
|  | *   Unimplemented | 
|  | */ | 
|  | BOOL WINAPI WriteConsoleOutputCharacterA( HANDLE hConsoleOutput, | 
|  | LPCSTR lpCharacter, DWORD nLength, COORD dwCoord, | 
|  | LPDWORD lpNumCharsWritten) | 
|  | { | 
|  | FIXME("(%d,%p,%ld,%dx%d,%p): stub\n", hConsoleOutput, | 
|  | lpCharacter,nLength,dwCoord.X,dwCoord.Y,lpNumCharsWritten); | 
|  | *lpNumCharsWritten = nLength; | 
|  | return TRUE; | 
|  | } | 
|  |  | 
|  | /****************************************************************************** | 
|  | * WriteConsoleOutputCharacterW [KERNEL32.@]  Copies character to consecutive | 
|  | * 					      cells in the console screen buffer | 
|  | * | 
|  | * PARAMS | 
|  | *    hConsoleOutput    [I] Handle to screen buffer | 
|  | *    lpCharacter       [I] Pointer to buffer with chars to write | 
|  | *    nLength           [I] Number of cells to write to | 
|  | *    dwCoord           [I] Coords of first cell | 
|  | *    lpNumCharsWritten [O] Pointer to number of cells written | 
|  | * | 
|  | * RETURNS | 
|  | *    Success: TRUE | 
|  | *    Failure: FALSE | 
|  | * | 
|  | * BUGS | 
|  | *   Unimplemented | 
|  | */ | 
|  | BOOL WINAPI WriteConsoleOutputCharacterW( HANDLE hConsoleOutput, | 
|  | LPCWSTR lpCharacter, DWORD nLength, COORD dwCoord, | 
|  | LPDWORD lpNumCharsWritten) | 
|  | { | 
|  | FIXME("(%d,%p,%ld,%dx%d,%p): stub\n", hConsoleOutput, | 
|  | lpCharacter,nLength,dwCoord.X,dwCoord.Y,lpNumCharsWritten); | 
|  | *lpNumCharsWritten = nLength; | 
|  | return TRUE; | 
|  | } |