kernel32: Remove old bare-console code.
[wine] / dlls / kernel32 / console.c
1 /*
2  * Win32 console functions
3  *
4  * Copyright 1995 Martin von Loewis and Cameron Heide
5  * Copyright 1997 Karl Garrison
6  * Copyright 1998 John Richardson
7  * Copyright 1998 Marcus Meissner
8  * Copyright 2001,2002,2004,2005 Eric Pouech
9  * Copyright 2001 Alexandre Julliard
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25
26 /* Reference applications:
27  * -  IDA (interactive disassembler) full version 3.75. Works.
28  * -  LYNX/W32. Works mostly, some keys crash it.
29  */
30
31 #include "config.h"
32 #include "wine/port.h"
33
34 #include <stdarg.h>
35 #include <stdio.h>
36 #include <string.h>
37 #ifdef HAVE_UNISTD_H
38 # include <unistd.h>
39 #endif
40 #include <assert.h>
41 #ifdef HAVE_TERMIOS_H
42 # include <termios.h>
43 #endif
44
45 #include "windef.h"
46 #include "winbase.h"
47 #include "winnls.h"
48 #include "winerror.h"
49 #include "wincon.h"
50 #include "wine/server.h"
51 #include "wine/exception.h"
52 #include "wine/unicode.h"
53 #include "wine/debug.h"
54 #include "excpt.h"
55 #include "console_private.h"
56 #include "kernel_private.h"
57
58 WINE_DEFAULT_DEBUG_CHANNEL(console);
59
60 static CRITICAL_SECTION CONSOLE_CritSect;
61 static CRITICAL_SECTION_DEBUG critsect_debug =
62 {
63     0, 0, &CONSOLE_CritSect,
64     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
65       0, 0, { (DWORD_PTR)(__FILE__ ": CONSOLE_CritSect") }
66 };
67 static CRITICAL_SECTION CONSOLE_CritSect = { &critsect_debug, -1, 0, 0, 0, 0 };
68
69 static const WCHAR coninW[] = {'C','O','N','I','N','$',0};
70 static const WCHAR conoutW[] = {'C','O','N','O','U','T','$',0};
71
72 /* FIXME: this is not thread safe */
73 static HANDLE console_wait_event;
74
75 /* map input records to ASCII */
76 static void input_records_WtoA( INPUT_RECORD *buffer, int count )
77 {
78     int i;
79     char ch;
80
81     for (i = 0; i < count; i++)
82     {
83         if (buffer[i].EventType != KEY_EVENT) continue;
84         WideCharToMultiByte( GetConsoleCP(), 0,
85                              &buffer[i].Event.KeyEvent.uChar.UnicodeChar, 1, &ch, 1, NULL, NULL );
86         buffer[i].Event.KeyEvent.uChar.AsciiChar = ch;
87     }
88 }
89
90 /* map input records to Unicode */
91 static void input_records_AtoW( INPUT_RECORD *buffer, int count )
92 {
93     int i;
94     WCHAR ch;
95
96     for (i = 0; i < count; i++)
97     {
98         if (buffer[i].EventType != KEY_EVENT) continue;
99         MultiByteToWideChar( GetConsoleCP(), 0,
100                              &buffer[i].Event.KeyEvent.uChar.AsciiChar, 1, &ch, 1 );
101         buffer[i].Event.KeyEvent.uChar.UnicodeChar = ch;
102     }
103 }
104
105 /* map char infos to ASCII */
106 static void char_info_WtoA( CHAR_INFO *buffer, int count )
107 {
108     char ch;
109
110     while (count-- > 0)
111     {
112         WideCharToMultiByte( GetConsoleOutputCP(), 0, &buffer->Char.UnicodeChar, 1,
113                              &ch, 1, NULL, NULL );
114         buffer->Char.AsciiChar = ch;
115         buffer++;
116     }
117 }
118
119 /* map char infos to Unicode */
120 static void char_info_AtoW( CHAR_INFO *buffer, int count )
121 {
122     WCHAR ch;
123
124     while (count-- > 0)
125     {
126         MultiByteToWideChar( GetConsoleOutputCP(), 0, &buffer->Char.AsciiChar, 1, &ch, 1 );
127         buffer->Char.UnicodeChar = ch;
128         buffer++;
129     }
130 }
131
132 static BOOL get_console_mode(HANDLE conin, DWORD* mode, BOOL* bare)
133 {
134     BOOL ret;
135
136     SERVER_START_REQ( get_console_mode )
137     {
138         req->handle = console_handle_unmap(conin);
139         if ((ret = !wine_server_call_err( req )))
140         {
141             if (mode) *mode = reply->mode;
142             if (bare) *bare = reply->is_bare;
143         }
144     }
145     SERVER_END_REQ;
146     return ret;
147 }
148
149 /******************************************************************************
150  * GetConsoleWindow [KERNEL32.@] Get hwnd of the console window.
151  *
152  * RETURNS
153  *   Success: hwnd of the console window.
154  *   Failure: NULL
155  */
156 HWND WINAPI GetConsoleWindow(VOID)
157 {
158     HWND hWnd = NULL;
159
160     SERVER_START_REQ(get_console_input_info)
161     {
162         req->handle = 0;
163         if (!wine_server_call_err(req)) hWnd = wine_server_ptr_handle( reply->win );
164     }
165     SERVER_END_REQ;
166
167     return hWnd;
168 }
169
170
171 /******************************************************************************
172  * GetConsoleCP [KERNEL32.@]  Returns the OEM code page for the console
173  *
174  * RETURNS
175  *    Code page code
176  */
177 UINT WINAPI GetConsoleCP(VOID)
178 {
179     BOOL ret;
180     UINT codepage = GetOEMCP(); /* default value */
181
182     SERVER_START_REQ(get_console_input_info)
183     {
184         req->handle = 0;
185         ret = !wine_server_call_err(req);
186         if (ret && reply->input_cp)
187             codepage = reply->input_cp;
188     }
189     SERVER_END_REQ;
190
191     return codepage;
192 }
193
194
195 /******************************************************************************
196  *  SetConsoleCP         [KERNEL32.@]
197  */
198 BOOL WINAPI SetConsoleCP(UINT cp)
199 {
200     BOOL ret;
201
202     if (!IsValidCodePage(cp))
203     {
204         SetLastError(ERROR_INVALID_PARAMETER);
205         return FALSE;
206     }
207
208     SERVER_START_REQ(set_console_input_info)
209     {
210         req->handle   = 0;
211         req->mask     = SET_CONSOLE_INPUT_INFO_INPUT_CODEPAGE;
212         req->input_cp = cp;
213         ret = !wine_server_call_err(req);
214     }
215     SERVER_END_REQ;
216
217     return ret;
218 }
219
220
221 /***********************************************************************
222  *            GetConsoleOutputCP   (KERNEL32.@)
223  */
224 UINT WINAPI GetConsoleOutputCP(VOID)
225 {
226     BOOL ret;
227     UINT codepage = GetOEMCP(); /* default value */
228
229     SERVER_START_REQ(get_console_input_info)
230     {
231         req->handle = 0;
232         ret = !wine_server_call_err(req);
233         if (ret && reply->output_cp)
234             codepage = reply->output_cp;
235     }
236     SERVER_END_REQ;
237
238     return codepage;
239 }
240
241
242 /******************************************************************************
243  * SetConsoleOutputCP [KERNEL32.@]  Set the output codepage used by the console
244  *
245  * PARAMS
246  *    cp [I] code page to set
247  *
248  * RETURNS
249  *    Success: TRUE
250  *    Failure: FALSE
251  */
252 BOOL WINAPI SetConsoleOutputCP(UINT cp)
253 {
254     BOOL ret;
255
256     if (!IsValidCodePage(cp))
257     {
258         SetLastError(ERROR_INVALID_PARAMETER);
259         return FALSE;
260     }
261
262     SERVER_START_REQ(set_console_input_info)
263     {
264         req->handle   = 0;
265         req->mask     = SET_CONSOLE_INPUT_INFO_OUTPUT_CODEPAGE;
266         req->output_cp = cp;
267         ret = !wine_server_call_err(req);
268     }
269     SERVER_END_REQ;
270
271     return ret;
272 }
273
274
275 /***********************************************************************
276  *           Beep   (KERNEL32.@)
277  */
278 BOOL WINAPI Beep( DWORD dwFreq, DWORD dwDur )
279 {
280     static const char beep = '\a';
281     /* dwFreq and dwDur are ignored by Win95 */
282     if (isatty(2)) write( 2, &beep, 1 );
283     return TRUE;
284 }
285
286
287 /******************************************************************
288  *              OpenConsoleW            (KERNEL32.@)
289  *
290  * Undocumented
291  *      Open a handle to the current process console.
292  *      Returns INVALID_HANDLE_VALUE on failure.
293  */
294 HANDLE WINAPI OpenConsoleW(LPCWSTR name, DWORD access, BOOL inherit, DWORD creation)
295 {
296     HANDLE      output = INVALID_HANDLE_VALUE;
297     HANDLE      ret;
298
299     TRACE("(%s, 0x%08x, %d, %u)\n", debugstr_w(name), access, inherit, creation);
300
301     if (name)
302     {
303         if (strcmpiW(coninW, name) == 0)
304             output = (HANDLE) FALSE;
305         else if (strcmpiW(conoutW, name) == 0)
306             output = (HANDLE) TRUE;
307     }
308
309     if (output == INVALID_HANDLE_VALUE)
310     {
311         SetLastError(ERROR_INVALID_PARAMETER);
312         return INVALID_HANDLE_VALUE;
313     }
314     else if (creation != OPEN_EXISTING)
315     {
316         if (!creation || creation == CREATE_NEW || creation == CREATE_ALWAYS)
317             SetLastError(ERROR_SHARING_VIOLATION);
318         else
319             SetLastError(ERROR_INVALID_PARAMETER);
320         return INVALID_HANDLE_VALUE;
321     }
322
323     SERVER_START_REQ( open_console )
324     {
325         req->from       = wine_server_obj_handle( output );
326         req->access     = access;
327         req->attributes = inherit ? OBJ_INHERIT : 0;
328         req->share      = FILE_SHARE_READ | FILE_SHARE_WRITE;
329         wine_server_call_err( req );
330         ret = wine_server_ptr_handle( reply->handle );
331     }
332     SERVER_END_REQ;
333     if (ret)
334         ret = console_handle_map(ret);
335
336     return ret;
337 }
338
339 /******************************************************************
340  *              VerifyConsoleIoHandle            (KERNEL32.@)
341  *
342  * Undocumented
343  */
344 BOOL WINAPI VerifyConsoleIoHandle(HANDLE handle)
345 {
346     BOOL ret;
347
348     if (!is_console_handle(handle)) return FALSE;
349     SERVER_START_REQ(get_console_mode)
350     {
351         req->handle = console_handle_unmap(handle);
352         ret = !wine_server_call_err( req );
353     }
354     SERVER_END_REQ;
355     return ret;
356 }
357
358 /******************************************************************
359  *              DuplicateConsoleHandle            (KERNEL32.@)
360  *
361  * Undocumented
362  */
363 HANDLE WINAPI DuplicateConsoleHandle(HANDLE handle, DWORD access, BOOL inherit,
364                                      DWORD options)
365 {
366     HANDLE      ret;
367
368     if (!is_console_handle(handle) ||
369         !DuplicateHandle(GetCurrentProcess(), wine_server_ptr_handle(console_handle_unmap(handle)),
370                          GetCurrentProcess(), &ret, access, inherit, options))
371         return INVALID_HANDLE_VALUE;
372     return console_handle_map(ret);
373 }
374
375 /******************************************************************
376  *              CloseConsoleHandle            (KERNEL32.@)
377  *
378  * Undocumented
379  */
380 BOOL WINAPI CloseConsoleHandle(HANDLE handle)
381 {
382     if (!is_console_handle(handle)) 
383     {
384         SetLastError(ERROR_INVALID_PARAMETER);
385         return FALSE;
386     }
387     return CloseHandle(wine_server_ptr_handle(console_handle_unmap(handle)));
388 }
389
390 /******************************************************************
391  *              GetConsoleInputWaitHandle            (KERNEL32.@)
392  *
393  * Undocumented
394  */
395 HANDLE WINAPI GetConsoleInputWaitHandle(void)
396 {
397     if (!console_wait_event)
398     {
399         SERVER_START_REQ(get_console_wait_event)
400         {
401             if (!wine_server_call_err( req ))
402                 console_wait_event = wine_server_ptr_handle( reply->handle );
403         }
404         SERVER_END_REQ;
405     }
406     return console_wait_event;
407 }
408
409
410 /******************************************************************************
411  * WriteConsoleInputA [KERNEL32.@]
412  */
413 BOOL WINAPI WriteConsoleInputA( HANDLE handle, const INPUT_RECORD *buffer,
414                                 DWORD count, LPDWORD written )
415 {
416     INPUT_RECORD *recW;
417     BOOL ret;
418
419     if (!(recW = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*recW) ))) return FALSE;
420     memcpy( recW, buffer, count*sizeof(*recW) );
421     input_records_AtoW( recW, count );
422     ret = WriteConsoleInputW( handle, recW, count, written );
423     HeapFree( GetProcessHeap(), 0, recW );
424     return ret;
425 }
426
427
428 /******************************************************************************
429  * WriteConsoleInputW [KERNEL32.@]
430  */
431 BOOL WINAPI WriteConsoleInputW( HANDLE handle, const INPUT_RECORD *buffer,
432                                 DWORD count, LPDWORD written )
433 {
434     BOOL ret;
435
436     TRACE("(%p,%p,%d,%p)\n", handle, buffer, count, written);
437
438     if (written) *written = 0;
439     SERVER_START_REQ( write_console_input )
440     {
441         req->handle = console_handle_unmap(handle);
442         wine_server_add_data( req, buffer, count * sizeof(INPUT_RECORD) );
443         if ((ret = !wine_server_call_err( req )) && written)
444             *written = reply->written;
445     }
446     SERVER_END_REQ;
447
448     return ret;
449 }
450
451
452 /***********************************************************************
453  *            WriteConsoleOutputA   (KERNEL32.@)
454  */
455 BOOL WINAPI WriteConsoleOutputA( HANDLE hConsoleOutput, const CHAR_INFO *lpBuffer,
456                                  COORD size, COORD coord, LPSMALL_RECT region )
457 {
458     int y;
459     BOOL ret;
460     COORD new_size, new_coord;
461     CHAR_INFO *ciw;
462
463     new_size.X = min( region->Right - region->Left + 1, size.X - coord.X );
464     new_size.Y = min( region->Bottom - region->Top + 1, size.Y - coord.Y );
465
466     if (new_size.X <= 0 || new_size.Y <= 0)
467     {
468         region->Bottom = region->Top + new_size.Y - 1;
469         region->Right = region->Left + new_size.X - 1;
470         return TRUE;
471     }
472
473     /* only copy the useful rectangle */
474     if (!(ciw = HeapAlloc( GetProcessHeap(), 0, sizeof(CHAR_INFO) * new_size.X * new_size.Y )))
475         return FALSE;
476     for (y = 0; y < new_size.Y; y++)
477     {
478         memcpy( &ciw[y * new_size.X], &lpBuffer[(y + coord.Y) * size.X + coord.X],
479                 new_size.X * sizeof(CHAR_INFO) );
480         char_info_AtoW( &ciw[ y * new_size.X ], new_size.X );
481     }
482     new_coord.X = new_coord.Y = 0;
483     ret = WriteConsoleOutputW( hConsoleOutput, ciw, new_size, new_coord, region );
484     HeapFree( GetProcessHeap(), 0, ciw );
485     return ret;
486 }
487
488
489 /***********************************************************************
490  *            WriteConsoleOutputW   (KERNEL32.@)
491  */
492 BOOL WINAPI WriteConsoleOutputW( HANDLE hConsoleOutput, const CHAR_INFO *lpBuffer,
493                                  COORD size, COORD coord, LPSMALL_RECT region )
494 {
495     int width, height, y;
496     BOOL ret = TRUE;
497
498     TRACE("(%p,%p,(%d,%d),(%d,%d),(%d,%dx%d,%d)\n",
499           hConsoleOutput, lpBuffer, size.X, size.Y, coord.X, coord.Y,
500           region->Left, region->Top, region->Right, region->Bottom);
501
502     width = min( region->Right - region->Left + 1, size.X - coord.X );
503     height = min( region->Bottom - region->Top + 1, size.Y - coord.Y );
504
505     if (width > 0 && height > 0)
506     {
507         for (y = 0; y < height; y++)
508         {
509             SERVER_START_REQ( write_console_output )
510             {
511                 req->handle = console_handle_unmap(hConsoleOutput);
512                 req->x      = region->Left;
513                 req->y      = region->Top + y;
514                 req->mode   = CHAR_INFO_MODE_TEXTATTR;
515                 req->wrap   = FALSE;
516                 wine_server_add_data( req, &lpBuffer[(y + coord.Y) * size.X + coord.X],
517                                       width * sizeof(CHAR_INFO));
518                 if ((ret = !wine_server_call_err( req )))
519                 {
520                     width  = min( width, reply->width - region->Left );
521                     height = min( height, reply->height - region->Top );
522                 }
523             }
524             SERVER_END_REQ;
525             if (!ret) break;
526         }
527     }
528     region->Bottom = region->Top + height - 1;
529     region->Right = region->Left + width - 1;
530     return ret;
531 }
532
533
534 /******************************************************************************
535  * WriteConsoleOutputCharacterA [KERNEL32.@]
536  *
537  * See WriteConsoleOutputCharacterW.
538  */
539 BOOL WINAPI WriteConsoleOutputCharacterA( HANDLE hConsoleOutput, LPCSTR str, DWORD length,
540                                           COORD coord, LPDWORD lpNumCharsWritten )
541 {
542     BOOL ret;
543     LPWSTR strW;
544     DWORD lenW;
545
546     TRACE("(%p,%s,%d,%dx%d,%p)\n", hConsoleOutput,
547           debugstr_an(str, length), length, coord.X, coord.Y, lpNumCharsWritten);
548
549     lenW = MultiByteToWideChar( GetConsoleOutputCP(), 0, str, length, NULL, 0 );
550
551     if (lpNumCharsWritten) *lpNumCharsWritten = 0;
552
553     if (!(strW = HeapAlloc( GetProcessHeap(), 0, lenW * sizeof(WCHAR) ))) return FALSE;
554     MultiByteToWideChar( GetConsoleOutputCP(), 0, str, length, strW, lenW );
555
556     ret = WriteConsoleOutputCharacterW( hConsoleOutput, strW, lenW, coord, lpNumCharsWritten );
557     HeapFree( GetProcessHeap(), 0, strW );
558     return ret;
559 }
560
561
562 /******************************************************************************
563  * WriteConsoleOutputAttribute [KERNEL32.@]  Sets attributes for some cells in
564  *                                           the console screen buffer
565  *
566  * PARAMS
567  *    hConsoleOutput    [I] Handle to screen buffer
568  *    attr              [I] Pointer to buffer with write attributes
569  *    length            [I] Number of cells to write to
570  *    coord             [I] Coords of first cell
571  *    lpNumAttrsWritten [O] Pointer to number of cells written
572  *
573  * RETURNS
574  *    Success: TRUE
575  *    Failure: FALSE
576  *
577  */
578 BOOL WINAPI WriteConsoleOutputAttribute( HANDLE hConsoleOutput, CONST WORD *attr, DWORD length,
579                                          COORD coord, LPDWORD lpNumAttrsWritten )
580 {
581     BOOL ret;
582
583     TRACE("(%p,%p,%d,%dx%d,%p)\n", hConsoleOutput,attr,length,coord.X,coord.Y,lpNumAttrsWritten);
584
585     SERVER_START_REQ( write_console_output )
586     {
587         req->handle = console_handle_unmap(hConsoleOutput);
588         req->x      = coord.X;
589         req->y      = coord.Y;
590         req->mode   = CHAR_INFO_MODE_ATTR;
591         req->wrap   = TRUE;
592         wine_server_add_data( req, attr, length * sizeof(WORD) );
593         if ((ret = !wine_server_call_err( req )))
594         {
595             if (lpNumAttrsWritten) *lpNumAttrsWritten = reply->written;
596         }
597     }
598     SERVER_END_REQ;
599     return ret;
600 }
601
602
603 /******************************************************************************
604  * FillConsoleOutputCharacterA [KERNEL32.@]
605  *
606  * See FillConsoleOutputCharacterW.
607  */
608 BOOL WINAPI FillConsoleOutputCharacterA( HANDLE hConsoleOutput, CHAR ch, DWORD length,
609                                          COORD coord, LPDWORD lpNumCharsWritten )
610 {
611     WCHAR wch;
612
613     MultiByteToWideChar( GetConsoleOutputCP(), 0, &ch, 1, &wch, 1 );
614     return FillConsoleOutputCharacterW(hConsoleOutput, wch, length, coord, lpNumCharsWritten);
615 }
616
617
618 /******************************************************************************
619  * FillConsoleOutputCharacterW [KERNEL32.@]  Writes characters to console
620  *
621  * PARAMS
622  *    hConsoleOutput    [I] Handle to screen buffer
623  *    ch                [I] Character to write
624  *    length            [I] Number of cells to write to
625  *    coord             [I] Coords of first cell
626  *    lpNumCharsWritten [O] Pointer to number of cells written
627  *
628  * RETURNS
629  *    Success: TRUE
630  *    Failure: FALSE
631  */
632 BOOL WINAPI FillConsoleOutputCharacterW( HANDLE hConsoleOutput, WCHAR ch, DWORD length,
633                                          COORD coord, LPDWORD lpNumCharsWritten)
634 {
635     BOOL ret;
636
637     TRACE("(%p,%s,%d,(%dx%d),%p)\n",
638           hConsoleOutput, debugstr_wn(&ch, 1), length, coord.X, coord.Y, lpNumCharsWritten);
639
640     SERVER_START_REQ( fill_console_output )
641     {
642         req->handle  = console_handle_unmap(hConsoleOutput);
643         req->x       = coord.X;
644         req->y       = coord.Y;
645         req->mode    = CHAR_INFO_MODE_TEXT;
646         req->wrap    = TRUE;
647         req->data.ch = ch;
648         req->count   = length;
649         if ((ret = !wine_server_call_err( req )))
650         {
651             if (lpNumCharsWritten) *lpNumCharsWritten = reply->written;
652         }
653     }
654     SERVER_END_REQ;
655     return ret;
656 }
657
658
659 /******************************************************************************
660  * FillConsoleOutputAttribute [KERNEL32.@]  Sets attributes for console
661  *
662  * PARAMS
663  *    hConsoleOutput    [I] Handle to screen buffer
664  *    attr              [I] Color attribute to write
665  *    length            [I] Number of cells to write to
666  *    coord             [I] Coords of first cell
667  *    lpNumAttrsWritten [O] Pointer to number of cells written
668  *
669  * RETURNS
670  *    Success: TRUE
671  *    Failure: FALSE
672  */
673 BOOL WINAPI FillConsoleOutputAttribute( HANDLE hConsoleOutput, WORD attr, DWORD length,
674                                         COORD coord, LPDWORD lpNumAttrsWritten )
675 {
676     BOOL ret;
677
678     TRACE("(%p,%d,%d,(%dx%d),%p)\n",
679           hConsoleOutput, attr, length, coord.X, coord.Y, lpNumAttrsWritten);
680
681     SERVER_START_REQ( fill_console_output )
682     {
683         req->handle    = console_handle_unmap(hConsoleOutput);
684         req->x         = coord.X;
685         req->y         = coord.Y;
686         req->mode      = CHAR_INFO_MODE_ATTR;
687         req->wrap      = TRUE;
688         req->data.attr = attr;
689         req->count     = length;
690         if ((ret = !wine_server_call_err( req )))
691         {
692             if (lpNumAttrsWritten) *lpNumAttrsWritten = reply->written;
693         }
694     }
695     SERVER_END_REQ;
696     return ret;
697 }
698
699
700 /******************************************************************************
701  * ReadConsoleOutputCharacterA [KERNEL32.@]
702  *
703  */
704 BOOL WINAPI ReadConsoleOutputCharacterA(HANDLE hConsoleOutput, LPSTR lpstr, DWORD count,
705                                         COORD coord, LPDWORD read_count)
706 {
707     DWORD read;
708     BOOL ret;
709     LPWSTR wptr = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR));
710
711     if (read_count) *read_count = 0;
712     if (!wptr) return FALSE;
713
714     if ((ret = ReadConsoleOutputCharacterW( hConsoleOutput, wptr, count, coord, &read )))
715     {
716         read = WideCharToMultiByte( GetConsoleOutputCP(), 0, wptr, read, lpstr, count, NULL, NULL);
717         if (read_count) *read_count = read;
718     }
719     HeapFree( GetProcessHeap(), 0, wptr );
720     return ret;
721 }
722
723
724 /******************************************************************************
725  * ReadConsoleOutputCharacterW [KERNEL32.@]
726  *
727  */
728 BOOL WINAPI ReadConsoleOutputCharacterW( HANDLE hConsoleOutput, LPWSTR buffer, DWORD count,
729                                          COORD coord, LPDWORD read_count )
730 {
731     BOOL ret;
732
733     TRACE( "(%p,%p,%d,%dx%d,%p)\n", hConsoleOutput, buffer, count, coord.X, coord.Y, read_count );
734
735     SERVER_START_REQ( read_console_output )
736     {
737         req->handle = console_handle_unmap(hConsoleOutput);
738         req->x      = coord.X;
739         req->y      = coord.Y;
740         req->mode   = CHAR_INFO_MODE_TEXT;
741         req->wrap   = TRUE;
742         wine_server_set_reply( req, buffer, count * sizeof(WCHAR) );
743         if ((ret = !wine_server_call_err( req )))
744         {
745             if (read_count) *read_count = wine_server_reply_size(reply) / sizeof(WCHAR);
746         }
747     }
748     SERVER_END_REQ;
749     return ret;
750 }
751
752
753 /******************************************************************************
754  *  ReadConsoleOutputAttribute [KERNEL32.@]
755  */
756 BOOL WINAPI ReadConsoleOutputAttribute(HANDLE hConsoleOutput, LPWORD lpAttribute, DWORD length,
757                                        COORD coord, LPDWORD read_count)
758 {
759     BOOL ret;
760
761     TRACE("(%p,%p,%d,%dx%d,%p)\n",
762           hConsoleOutput, lpAttribute, length, coord.X, coord.Y, read_count);
763
764     SERVER_START_REQ( read_console_output )
765     {
766         req->handle = console_handle_unmap(hConsoleOutput);
767         req->x      = coord.X;
768         req->y      = coord.Y;
769         req->mode   = CHAR_INFO_MODE_ATTR;
770         req->wrap   = TRUE;
771         wine_server_set_reply( req, lpAttribute, length * sizeof(WORD) );
772         if ((ret = !wine_server_call_err( req )))
773         {
774             if (read_count) *read_count = wine_server_reply_size(reply) / sizeof(WORD);
775         }
776     }
777     SERVER_END_REQ;
778     return ret;
779 }
780
781
782 /******************************************************************************
783  *  ReadConsoleOutputA [KERNEL32.@]
784  *
785  */
786 BOOL WINAPI ReadConsoleOutputA( HANDLE hConsoleOutput, LPCHAR_INFO lpBuffer, COORD size,
787                                 COORD coord, LPSMALL_RECT region )
788 {
789     BOOL ret;
790     int y;
791
792     ret = ReadConsoleOutputW( hConsoleOutput, lpBuffer, size, coord, region );
793     if (ret && region->Right >= region->Left)
794     {
795         for (y = 0; y <= region->Bottom - region->Top; y++)
796         {
797             char_info_WtoA( &lpBuffer[(coord.Y + y) * size.X + coord.X],
798                             region->Right - region->Left + 1 );
799         }
800     }
801     return ret;
802 }
803
804
805 /******************************************************************************
806  *  ReadConsoleOutputW [KERNEL32.@]
807  *
808  * NOTE: The NT4 (sp5) kernel crashes on me if size is (0,0). I don't
809  * think we need to be *that* compatible.  -- AJ
810  */
811 BOOL WINAPI ReadConsoleOutputW( HANDLE hConsoleOutput, LPCHAR_INFO lpBuffer, COORD size,
812                                 COORD coord, LPSMALL_RECT region )
813 {
814     int width, height, y;
815     BOOL ret = TRUE;
816
817     width = min( region->Right - region->Left + 1, size.X - coord.X );
818     height = min( region->Bottom - region->Top + 1, size.Y - coord.Y );
819
820     if (width > 0 && height > 0)
821     {
822         for (y = 0; y < height; y++)
823         {
824             SERVER_START_REQ( read_console_output )
825             {
826                 req->handle = console_handle_unmap(hConsoleOutput);
827                 req->x      = region->Left;
828                 req->y      = region->Top + y;
829                 req->mode   = CHAR_INFO_MODE_TEXTATTR;
830                 req->wrap   = FALSE;
831                 wine_server_set_reply( req, &lpBuffer[(y+coord.Y) * size.X + coord.X],
832                                        width * sizeof(CHAR_INFO) );
833                 if ((ret = !wine_server_call_err( req )))
834                 {
835                     width  = min( width, reply->width - region->Left );
836                     height = min( height, reply->height - region->Top );
837                 }
838             }
839             SERVER_END_REQ;
840             if (!ret) break;
841         }
842     }
843     region->Bottom = region->Top + height - 1;
844     region->Right = region->Left + width - 1;
845     return ret;
846 }
847
848
849 /******************************************************************************
850  * ReadConsoleInputA [KERNEL32.@]  Reads data from a console
851  *
852  * PARAMS
853  *    handle   [I] Handle to console input buffer
854  *    buffer   [O] Address of buffer for read data
855  *    count    [I] Number of records to read
856  *    pRead    [O] Address of number of records read
857  *
858  * RETURNS
859  *    Success: TRUE
860  *    Failure: FALSE
861  */
862 BOOL WINAPI ReadConsoleInputA( HANDLE handle, PINPUT_RECORD buffer, DWORD count, LPDWORD pRead )
863 {
864     DWORD read;
865
866     if (!ReadConsoleInputW( handle, buffer, count, &read )) return FALSE;
867     input_records_WtoA( buffer, read );
868     if (pRead) *pRead = read;
869     return TRUE;
870 }
871
872
873 /***********************************************************************
874  *            PeekConsoleInputA   (KERNEL32.@)
875  *
876  * Gets 'count' first events (or less) from input queue.
877  */
878 BOOL WINAPI PeekConsoleInputA( HANDLE handle, PINPUT_RECORD buffer, DWORD count, LPDWORD pRead )
879 {
880     DWORD read;
881
882     if (!PeekConsoleInputW( handle, buffer, count, &read )) return FALSE;
883     input_records_WtoA( buffer, read );
884     if (pRead) *pRead = read;
885     return TRUE;
886 }
887
888
889 /***********************************************************************
890  *            PeekConsoleInputW   (KERNEL32.@)
891  */
892 BOOL WINAPI PeekConsoleInputW( HANDLE handle, PINPUT_RECORD buffer, DWORD count, LPDWORD read )
893 {
894     BOOL ret;
895     SERVER_START_REQ( read_console_input )
896     {
897         req->handle = console_handle_unmap(handle);
898         req->flush  = FALSE;
899         wine_server_set_reply( req, buffer, count * sizeof(INPUT_RECORD) );
900         if ((ret = !wine_server_call_err( req )))
901         {
902             if (read) *read = count ? reply->read : 0;
903         }
904     }
905     SERVER_END_REQ;
906     return ret;
907 }
908
909
910 /***********************************************************************
911  *            GetNumberOfConsoleInputEvents   (KERNEL32.@)
912  */
913 BOOL WINAPI GetNumberOfConsoleInputEvents( HANDLE handle, LPDWORD nrofevents )
914 {
915     BOOL ret;
916     SERVER_START_REQ( read_console_input )
917     {
918         req->handle = console_handle_unmap(handle);
919         req->flush  = FALSE;
920         if ((ret = !wine_server_call_err( req )))
921         {
922             if (nrofevents) *nrofevents = reply->read;
923         }
924     }
925     SERVER_END_REQ;
926     return ret;
927 }
928
929
930 /******************************************************************************
931  * read_console_input
932  *
933  * Helper function for ReadConsole, ReadConsoleInput and FlushConsoleInputBuffer
934  *
935  * Returns
936  *      0 for error, 1 for no INPUT_RECORD ready, 2 with INPUT_RECORD ready
937  */
938 enum read_console_input_return {rci_error = 0, rci_timeout = 1, rci_gotone = 2};
939 static const int vkkeyscan_table[256] =
940 {
941      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,
942      0,32,305,478,307,308,309,311,222,313,304,312,443,188,189,190,191,48,
943      49,50,51,52,53,54,55,56,57,442,186,444,187,446,447,306,321,322,323,
944      324,325,326,327,328,329,330,331,332,333,334,335,336,337,338,339,340,
945      341,342,343,344,345,346,219,220,221,310,445,192,65,66,67,68,69,70,71,
946      72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,475,476,477,
947      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,
948      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
949      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
950      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
951 };
952
953 static const int mapvkey_0[256] =
954 {
955      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,
956      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,
957      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,
958      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,
959      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,
960      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,
961      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,
962      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,
963      0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
964 };
965
966 static inline void init_complex_char(INPUT_RECORD* ir, BOOL down, WORD vk, WORD kc, DWORD cks)
967 {
968     ir->EventType                        = KEY_EVENT;
969     ir->Event.KeyEvent.bKeyDown          = down;
970     ir->Event.KeyEvent.wRepeatCount      = 1;
971     ir->Event.KeyEvent.wVirtualScanCode  = vk;
972     ir->Event.KeyEvent.wVirtualKeyCode   = kc;
973     ir->Event.KeyEvent.dwControlKeyState = cks;
974     ir->Event.KeyEvent.uChar.UnicodeChar = 0;
975 }
976
977 /******************************************************************
978  *              handle_simple_char
979  *
980  *
981  */
982 static BOOL handle_simple_char(HANDLE conin, unsigned real_inchar)
983 {
984     unsigned            vk;
985     unsigned            inchar;
986     char                ch;
987     unsigned            numEvent = 0;
988     DWORD               cks = 0, written;
989     INPUT_RECORD        ir[8];
990
991     switch (real_inchar)
992     {
993     case   9: inchar = real_inchar;
994         real_inchar = 27; /* so that we don't think key is ctrl- something */
995         break;
996     case  13:
997     case  10: inchar = '\r';
998         real_inchar = 27; /* Fixme: so that we don't think key is ctrl- something */
999         break;
1000     case 127: inchar = '\b';
1001         break;
1002     default:
1003         inchar = real_inchar;
1004         break;
1005     }
1006     if ((inchar & ~0xFF) != 0) FIXME("What a char (%u)\n", inchar);
1007     vk = vkkeyscan_table[inchar];
1008     if (vk & 0x0100)
1009         init_complex_char(&ir[numEvent++], 1, 0x2a, 0x10, SHIFT_PRESSED);
1010     if ((vk & 0x0200) || (unsigned char)real_inchar <= 26)
1011         init_complex_char(&ir[numEvent++], 1, 0x1d, 0x11, LEFT_CTRL_PRESSED);
1012     if (vk & 0x0400)
1013         init_complex_char(&ir[numEvent++], 1, 0x38, 0x12, LEFT_ALT_PRESSED);
1014
1015     ir[numEvent].EventType                        = KEY_EVENT;
1016     ir[numEvent].Event.KeyEvent.bKeyDown          = 1;
1017     ir[numEvent].Event.KeyEvent.wRepeatCount      = 1;
1018     ir[numEvent].Event.KeyEvent.dwControlKeyState = cks;
1019     if (vk & 0x0100)
1020         ir[numEvent].Event.KeyEvent.dwControlKeyState |= SHIFT_PRESSED;
1021     if ((vk & 0x0200) || (unsigned char)real_inchar <= 26)
1022         ir[numEvent].Event.KeyEvent.dwControlKeyState |= LEFT_CTRL_PRESSED;
1023     if (vk & 0x0400)
1024         ir[numEvent].Event.KeyEvent.dwControlKeyState |= LEFT_ALT_PRESSED;
1025     ir[numEvent].Event.KeyEvent.wVirtualKeyCode = vk;
1026     ir[numEvent].Event.KeyEvent.wVirtualScanCode = mapvkey_0[vk & 0x00ff]; /* VirtualKeyCodes to ScanCode */
1027
1028     ch = inchar;
1029     MultiByteToWideChar(CP_UNIXCP, 0, &ch, 1, &ir[numEvent].Event.KeyEvent.uChar.UnicodeChar, 1);
1030     ir[numEvent + 1] = ir[numEvent];
1031     ir[numEvent + 1].Event.KeyEvent.bKeyDown = 0;
1032
1033     numEvent += 2;
1034
1035     if (vk & 0x0400)
1036         init_complex_char(&ir[numEvent++], 0, 0x38, 0x12, LEFT_ALT_PRESSED);
1037     if ((vk & 0x0200) || (unsigned char)real_inchar <= 26)
1038         init_complex_char(&ir[numEvent++], 0, 0x1d, 0x11, 0);
1039     if (vk & 0x0100)
1040         init_complex_char(&ir[numEvent++], 0, 0x2a, 0x10, 0);
1041
1042     return WriteConsoleInputW(conin, ir, numEvent, &written);
1043 }
1044
1045 static enum read_console_input_return bare_console_fetch_input(HANDLE handle, DWORD timeout)
1046 {
1047     OVERLAPPED                          ov;
1048     enum read_console_input_return      ret;
1049     char                                ch;
1050
1051     /* get the real handle to the console object */
1052     handle = wine_server_ptr_handle(console_handle_unmap(handle));
1053
1054     memset(&ov, 0, sizeof(ov));
1055     ov.hEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
1056
1057     if (ReadFile(handle, &ch, 1, NULL, &ov) ||
1058         (GetLastError() == ERROR_IO_PENDING &&
1059          WaitForSingleObject(ov.hEvent, timeout) == WAIT_OBJECT_0 &&
1060          GetOverlappedResult(handle, &ov, NULL, FALSE)))
1061     {
1062         ret = handle_simple_char(handle, ch) ? rci_gotone : rci_error;
1063     }
1064     else
1065     {
1066         WARN("Failed read %x\n", GetLastError());
1067         ret = rci_error;
1068     }
1069     CloseHandle(ov.hEvent);
1070
1071     return ret;
1072 }
1073
1074 static enum read_console_input_return read_console_input(HANDLE handle, PINPUT_RECORD ir, DWORD timeout)
1075 {
1076     BOOL bare;
1077     enum read_console_input_return      ret;
1078
1079     if (!get_console_mode(handle, NULL, &bare)) return rci_error;
1080
1081     if (bare)
1082     {
1083         if (WaitForSingleObject(GetConsoleInputWaitHandle(), 0) != WAIT_OBJECT_0)
1084         {
1085             ret = bare_console_fetch_input(handle, timeout);
1086             if (ret != rci_gotone) return ret;
1087         }
1088     }
1089     else
1090     {
1091         if (WaitForSingleObject(GetConsoleInputWaitHandle(), timeout) != WAIT_OBJECT_0)
1092             return rci_timeout;
1093     }
1094
1095     SERVER_START_REQ( read_console_input )
1096     {
1097         req->handle = console_handle_unmap(handle);
1098         req->flush = TRUE;
1099         wine_server_set_reply( req, ir, sizeof(INPUT_RECORD) );
1100         if (wine_server_call_err( req ) || !reply->read) ret = rci_error;
1101         else ret = rci_gotone;
1102     }
1103     SERVER_END_REQ;
1104
1105     return ret;
1106 }
1107
1108
1109 /***********************************************************************
1110  *            FlushConsoleInputBuffer   (KERNEL32.@)
1111  */
1112 BOOL WINAPI FlushConsoleInputBuffer( HANDLE handle )
1113 {
1114     enum read_console_input_return      last;
1115     INPUT_RECORD                        ir;
1116
1117     while ((last = read_console_input(handle, &ir, 0)) == rci_gotone);
1118
1119     return last == rci_timeout;
1120 }
1121
1122
1123 /***********************************************************************
1124  *            SetConsoleTitleA   (KERNEL32.@)
1125  */
1126 BOOL WINAPI SetConsoleTitleA( LPCSTR title )
1127 {
1128     LPWSTR titleW;
1129     BOOL ret;
1130
1131     DWORD len = MultiByteToWideChar( GetConsoleOutputCP(), 0, title, -1, NULL, 0 );
1132     if (!(titleW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)))) return FALSE;
1133     MultiByteToWideChar( GetConsoleOutputCP(), 0, title, -1, titleW, len );
1134     ret = SetConsoleTitleW(titleW);
1135     HeapFree(GetProcessHeap(), 0, titleW);
1136     return ret;
1137 }
1138
1139
1140 /***********************************************************************
1141  *            GetConsoleKeyboardLayoutNameA   (KERNEL32.@)
1142  */
1143 BOOL WINAPI GetConsoleKeyboardLayoutNameA(LPSTR layoutName)
1144 {
1145     FIXME( "stub %p\n", layoutName);
1146     return TRUE;
1147 }
1148
1149 /***********************************************************************
1150  *            GetConsoleKeyboardLayoutNameW   (KERNEL32.@)
1151  */
1152 BOOL WINAPI GetConsoleKeyboardLayoutNameW(LPWSTR layoutName)
1153 {
1154     FIXME( "stub %p\n", layoutName);
1155     return TRUE;
1156 }
1157
1158 static WCHAR input_exe[MAX_PATH + 1];
1159
1160 /***********************************************************************
1161  *            GetConsoleInputExeNameW   (KERNEL32.@)
1162  */
1163 BOOL WINAPI GetConsoleInputExeNameW(DWORD buflen, LPWSTR buffer)
1164 {
1165     TRACE("%u %p\n", buflen, buffer);
1166
1167     RtlEnterCriticalSection(&CONSOLE_CritSect);
1168     if (buflen > strlenW(input_exe)) strcpyW(buffer, input_exe);
1169     else SetLastError(ERROR_BUFFER_OVERFLOW);
1170     RtlLeaveCriticalSection(&CONSOLE_CritSect);
1171
1172     return TRUE;
1173 }
1174
1175 /***********************************************************************
1176  *            GetConsoleInputExeNameA   (KERNEL32.@)
1177  */
1178 BOOL WINAPI GetConsoleInputExeNameA(DWORD buflen, LPSTR buffer)
1179 {
1180     TRACE("%u %p\n", buflen, buffer);
1181
1182     RtlEnterCriticalSection(&CONSOLE_CritSect);
1183     if (WideCharToMultiByte(CP_ACP, 0, input_exe, -1, NULL, 0, NULL, NULL) <= buflen)
1184         WideCharToMultiByte(CP_ACP, 0, input_exe, -1, buffer, buflen, NULL, NULL);
1185     else SetLastError(ERROR_BUFFER_OVERFLOW);
1186     RtlLeaveCriticalSection(&CONSOLE_CritSect);
1187
1188     return TRUE;
1189 }
1190
1191 /***********************************************************************
1192  *            GetConsoleTitleA   (KERNEL32.@)
1193  *
1194  * See GetConsoleTitleW.
1195  */
1196 DWORD WINAPI GetConsoleTitleA(LPSTR title, DWORD size)
1197 {
1198     WCHAR *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * size);
1199     DWORD ret;
1200
1201     if (!ptr) return 0;
1202     ret = GetConsoleTitleW( ptr, size );
1203     if (ret)
1204     {
1205         WideCharToMultiByte( GetConsoleOutputCP(), 0, ptr, ret + 1, title, size, NULL, NULL);
1206         ret = strlen(title);
1207     }
1208     HeapFree(GetProcessHeap(), 0, ptr);
1209     return ret;
1210 }
1211
1212
1213 /******************************************************************************
1214  * GetConsoleTitleW [KERNEL32.@]  Retrieves title string for console
1215  *
1216  * PARAMS
1217  *    title [O] Address of buffer for title
1218  *    size  [I] Size of buffer
1219  *
1220  * RETURNS
1221  *    Success: Length of string copied
1222  *    Failure: 0
1223  */
1224 DWORD WINAPI GetConsoleTitleW(LPWSTR title, DWORD size)
1225 {
1226     DWORD ret = 0;
1227
1228     SERVER_START_REQ( get_console_input_info )
1229     {
1230         req->handle = 0;
1231         wine_server_set_reply( req, title, (size-1) * sizeof(WCHAR) );
1232         if (!wine_server_call_err( req ))
1233         {
1234             ret = wine_server_reply_size(reply) / sizeof(WCHAR);
1235             title[ret] = 0;
1236         }
1237     }
1238     SERVER_END_REQ;
1239     return ret;
1240 }
1241
1242
1243 /***********************************************************************
1244  *            GetLargestConsoleWindowSize   (KERNEL32.@)
1245  *
1246  * NOTE
1247  *      This should return a COORD, but calling convention for returning
1248  *      structures is different between Windows and gcc on i386.
1249  *
1250  * VERSION: [i386]
1251  */
1252 #ifdef __i386__
1253 #undef GetLargestConsoleWindowSize
1254 DWORD WINAPI GetLargestConsoleWindowSize(HANDLE hConsoleOutput)
1255 {
1256     union {
1257         COORD c;
1258         DWORD w;
1259     } x;
1260     x.c.X = 80;
1261     x.c.Y = 24;
1262     TRACE("(%p), returning %dx%d (%x)\n", hConsoleOutput, x.c.X, x.c.Y, x.w);
1263     return x.w;
1264 }
1265 #endif /* defined(__i386__) */
1266
1267
1268 /***********************************************************************
1269  *            GetLargestConsoleWindowSize   (KERNEL32.@)
1270  *
1271  * NOTE
1272  *      This should return a COORD, but calling convention for returning
1273  *      structures is different between Windows and gcc on i386.
1274  *
1275  * VERSION: [!i386]
1276  */
1277 #ifndef __i386__
1278 COORD WINAPI GetLargestConsoleWindowSize(HANDLE hConsoleOutput)
1279 {
1280     COORD c;
1281     c.X = 80;
1282     c.Y = 24;
1283     TRACE("(%p), returning %dx%d\n", hConsoleOutput, c.X, c.Y);
1284     return c;
1285 }
1286 #endif /* defined(__i386__) */
1287
1288 static WCHAR*   S_EditString /* = NULL */;
1289 static unsigned S_EditStrPos /* = 0 */;
1290
1291 /***********************************************************************
1292  *            FreeConsole (KERNEL32.@)
1293  */
1294 BOOL WINAPI FreeConsole(VOID)
1295 {
1296     BOOL ret;
1297
1298     /* invalidate local copy of input event handle */
1299     console_wait_event = 0;
1300
1301     SERVER_START_REQ(free_console)
1302     {
1303         ret = !wine_server_call_err( req );
1304     }
1305     SERVER_END_REQ;
1306     return ret;
1307 }
1308
1309 /******************************************************************
1310  *              start_console_renderer
1311  *
1312  * helper for AllocConsole
1313  * starts the renderer process
1314  */
1315 static  BOOL    start_console_renderer_helper(const char* appname, STARTUPINFOA* si,
1316                                               HANDLE hEvent)
1317 {
1318     char                buffer[1024];
1319     int                 ret;
1320     PROCESS_INFORMATION pi;
1321
1322     /* FIXME: use dynamic allocation for most of the buffers below */
1323     ret = snprintf(buffer, sizeof(buffer), "%s --use-event=%ld", appname, (DWORD_PTR)hEvent);
1324     if ((ret > -1) && (ret < sizeof(buffer)) &&
1325         CreateProcessA(NULL, buffer, NULL, NULL, TRUE, DETACHED_PROCESS,
1326                        NULL, NULL, si, &pi))
1327     {
1328         HANDLE  wh[2];
1329         DWORD   ret;
1330
1331         wh[0] = hEvent;
1332         wh[1] = pi.hProcess;
1333         ret = WaitForMultipleObjects(2, wh, FALSE, INFINITE);
1334
1335         CloseHandle(pi.hThread);
1336         CloseHandle(pi.hProcess);
1337
1338         if (ret != WAIT_OBJECT_0) return FALSE;
1339
1340         TRACE("Started wineconsole pid=%08x tid=%08x\n",
1341               pi.dwProcessId, pi.dwThreadId);
1342
1343         return TRUE;
1344     }
1345     return FALSE;
1346 }
1347
1348 static  BOOL    start_console_renderer(STARTUPINFOA* si)
1349 {
1350     HANDLE              hEvent = 0;
1351     LPSTR               p;
1352     OBJECT_ATTRIBUTES   attr;
1353     BOOL                ret = FALSE;
1354
1355     attr.Length                   = sizeof(attr);
1356     attr.RootDirectory            = 0;
1357     attr.Attributes               = OBJ_INHERIT;
1358     attr.ObjectName               = NULL;
1359     attr.SecurityDescriptor       = NULL;
1360     attr.SecurityQualityOfService = NULL;
1361
1362     NtCreateEvent(&hEvent, EVENT_ALL_ACCESS, &attr, NotificationEvent, FALSE);
1363     if (!hEvent) return FALSE;
1364
1365     /* first try environment variable */
1366     if ((p = getenv("WINECONSOLE")) != NULL)
1367     {
1368         ret = start_console_renderer_helper(p, si, hEvent);
1369         if (!ret)
1370             ERR("Couldn't launch Wine console from WINECONSOLE env var (%s)... "
1371                 "trying default access\n", p);
1372     }
1373
1374     /* then try the regular PATH */
1375     if (!ret)
1376         ret = start_console_renderer_helper("wineconsole", si, hEvent);
1377
1378     CloseHandle(hEvent);
1379     return ret;
1380 }
1381
1382 /***********************************************************************
1383  *            AllocConsole (KERNEL32.@)
1384  *
1385  * creates an xterm with a pty to our program
1386  */
1387 BOOL WINAPI AllocConsole(void)
1388 {
1389     HANDLE              handle_in = INVALID_HANDLE_VALUE;
1390     HANDLE              handle_out = INVALID_HANDLE_VALUE;
1391     HANDLE              handle_err = INVALID_HANDLE_VALUE;
1392     STARTUPINFOA        siCurrent;
1393     STARTUPINFOA        siConsole;
1394     char                buffer[1024];
1395
1396     TRACE("()\n");
1397
1398     handle_in = OpenConsoleW( coninW, GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,
1399                               FALSE, OPEN_EXISTING );
1400
1401     if (VerifyConsoleIoHandle(handle_in))
1402     {
1403         /* we already have a console opened on this process, don't create a new one */
1404         CloseHandle(handle_in);
1405         return FALSE;
1406     }
1407
1408     /* invalidate local copy of input event handle */
1409     console_wait_event = 0;
1410
1411     GetStartupInfoA(&siCurrent);
1412
1413     memset(&siConsole, 0, sizeof(siConsole));
1414     siConsole.cb = sizeof(siConsole);
1415     /* setup a view arguments for wineconsole (it'll use them as default values)  */
1416     if (siCurrent.dwFlags & STARTF_USECOUNTCHARS)
1417     {
1418         siConsole.dwFlags |= STARTF_USECOUNTCHARS;
1419         siConsole.dwXCountChars = siCurrent.dwXCountChars;
1420         siConsole.dwYCountChars = siCurrent.dwYCountChars;
1421     }
1422     if (siCurrent.dwFlags & STARTF_USEFILLATTRIBUTE)
1423     {
1424         siConsole.dwFlags |= STARTF_USEFILLATTRIBUTE;
1425         siConsole.dwFillAttribute = siCurrent.dwFillAttribute;
1426     }
1427     if (siCurrent.dwFlags & STARTF_USESHOWWINDOW)
1428     {
1429         siConsole.dwFlags |= STARTF_USESHOWWINDOW;
1430         siConsole.wShowWindow = siCurrent.wShowWindow;
1431     }
1432     /* FIXME (should pass the unicode form) */
1433     if (siCurrent.lpTitle)
1434         siConsole.lpTitle = siCurrent.lpTitle;
1435     else if (GetModuleFileNameA(0, buffer, sizeof(buffer)))
1436     {
1437         buffer[sizeof(buffer) - 1] = '\0';
1438         siConsole.lpTitle = buffer;
1439     }
1440
1441     if (!start_console_renderer(&siConsole))
1442         goto the_end;
1443
1444     if( !(siCurrent.dwFlags & STARTF_USESTDHANDLES) ) {
1445         /* all std I/O handles are inheritable by default */
1446         handle_in = OpenConsoleW( coninW, GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,
1447                                   TRUE, OPEN_EXISTING );
1448         if (handle_in == INVALID_HANDLE_VALUE) goto the_end;
1449   
1450         handle_out = OpenConsoleW( conoutW, GENERIC_READ|GENERIC_WRITE,
1451                                    TRUE, OPEN_EXISTING );
1452         if (handle_out == INVALID_HANDLE_VALUE) goto the_end;
1453   
1454         if (!DuplicateHandle(GetCurrentProcess(), handle_out, GetCurrentProcess(),
1455                     &handle_err, 0, TRUE, DUPLICATE_SAME_ACCESS))
1456             goto the_end;
1457     } else {
1458         /*  STARTF_USESTDHANDLES flag: use handles from StartupInfo */
1459         handle_in  =  siCurrent.hStdInput;
1460         handle_out =  siCurrent.hStdOutput;
1461         handle_err =  siCurrent.hStdError;
1462     }
1463
1464     /* NT resets the STD_*_HANDLEs on console alloc */
1465     SetStdHandle(STD_INPUT_HANDLE,  handle_in);
1466     SetStdHandle(STD_OUTPUT_HANDLE, handle_out);
1467     SetStdHandle(STD_ERROR_HANDLE,  handle_err);
1468
1469     SetLastError(ERROR_SUCCESS);
1470
1471     return TRUE;
1472
1473  the_end:
1474     ERR("Can't allocate console\n");
1475     if (handle_in != INVALID_HANDLE_VALUE)      CloseHandle(handle_in);
1476     if (handle_out != INVALID_HANDLE_VALUE)     CloseHandle(handle_out);
1477     if (handle_err != INVALID_HANDLE_VALUE)     CloseHandle(handle_err);
1478     FreeConsole();
1479     return FALSE;
1480 }
1481
1482
1483 /***********************************************************************
1484  *            ReadConsoleA   (KERNEL32.@)
1485  */
1486 BOOL WINAPI ReadConsoleA(HANDLE hConsoleInput, LPVOID lpBuffer, DWORD nNumberOfCharsToRead,
1487                          LPDWORD lpNumberOfCharsRead, LPVOID lpReserved)
1488 {
1489     LPWSTR      ptr = HeapAlloc(GetProcessHeap(), 0, nNumberOfCharsToRead * sizeof(WCHAR));
1490     DWORD       ncr = 0;
1491     BOOL        ret;
1492
1493     if ((ret = ReadConsoleW(hConsoleInput, ptr, nNumberOfCharsToRead, &ncr, NULL)))
1494         ncr = WideCharToMultiByte(GetConsoleCP(), 0, ptr, ncr, lpBuffer, nNumberOfCharsToRead, NULL, NULL);
1495
1496     if (lpNumberOfCharsRead) *lpNumberOfCharsRead = ncr;
1497     HeapFree(GetProcessHeap(), 0, ptr);
1498
1499     return ret;
1500 }
1501
1502 /***********************************************************************
1503  *            ReadConsoleW   (KERNEL32.@)
1504  */
1505 BOOL WINAPI ReadConsoleW(HANDLE hConsoleInput, LPVOID lpBuffer,
1506                          DWORD nNumberOfCharsToRead, LPDWORD lpNumberOfCharsRead, LPVOID lpReserved)
1507 {
1508     DWORD       charsread;
1509     LPWSTR      xbuf = lpBuffer;
1510     DWORD       mode;
1511     BOOL        is_bare;
1512
1513     TRACE("(%p,%p,%d,%p,%p)\n",
1514           hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, lpReserved);
1515
1516     if (!get_console_mode(hConsoleInput, &mode, &is_bare))
1517         return FALSE;
1518
1519     if (mode & ENABLE_LINE_INPUT)
1520     {
1521         if (!S_EditString || S_EditString[S_EditStrPos] == 0)
1522         {
1523             HeapFree(GetProcessHeap(), 0, S_EditString);
1524             if (!(S_EditString = CONSOLE_Readline(hConsoleInput, !is_bare)))
1525                 return FALSE;
1526             S_EditStrPos = 0;
1527         }
1528         charsread = lstrlenW(&S_EditString[S_EditStrPos]);
1529         if (charsread > nNumberOfCharsToRead) charsread = nNumberOfCharsToRead;
1530         memcpy(xbuf, &S_EditString[S_EditStrPos], charsread * sizeof(WCHAR));
1531         S_EditStrPos += charsread;
1532     }
1533     else
1534     {
1535         INPUT_RECORD    ir;
1536         DWORD           timeout = INFINITE;
1537
1538         /* FIXME: should we read at least 1 char? The SDK does not say */
1539         /* wait for at least one available input record (it doesn't mean we'll have
1540          * chars stored in xbuf...)
1541          *
1542          * Although SDK doc keeps silence about 1 char, SDK examples assume
1543          * that we should wait for at least one character (not key). --KS
1544          */
1545         charsread = 0;
1546         do 
1547         {
1548             if (read_console_input(hConsoleInput, &ir, timeout) != rci_gotone) break;
1549             if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown &&
1550                 ir.Event.KeyEvent.uChar.UnicodeChar)
1551             {
1552                 xbuf[charsread++] = ir.Event.KeyEvent.uChar.UnicodeChar;
1553                 timeout = 0;
1554             }
1555         } while (charsread < nNumberOfCharsToRead);
1556         /* nothing has been read */
1557         if (timeout == INFINITE) return FALSE;
1558     }
1559
1560     if (lpNumberOfCharsRead) *lpNumberOfCharsRead = charsread;
1561
1562     return TRUE;
1563 }
1564
1565
1566 /***********************************************************************
1567  *            ReadConsoleInputW   (KERNEL32.@)
1568  */
1569 BOOL WINAPI ReadConsoleInputW(HANDLE hConsoleInput, PINPUT_RECORD lpBuffer,
1570                               DWORD nLength, LPDWORD lpNumberOfEventsRead)
1571 {
1572     DWORD idx = 0;
1573     DWORD timeout = INFINITE;
1574
1575     if (!nLength)
1576     {
1577         if (lpNumberOfEventsRead) *lpNumberOfEventsRead = 0;
1578         return TRUE;
1579     }
1580
1581     /* loop until we get at least one event */
1582     while (read_console_input(hConsoleInput, &lpBuffer[idx], timeout) == rci_gotone &&
1583            ++idx < nLength)
1584         timeout = 0;
1585
1586     if (lpNumberOfEventsRead) *lpNumberOfEventsRead = idx;
1587     return idx != 0;
1588 }
1589
1590
1591 /******************************************************************************
1592  * WriteConsoleOutputCharacterW [KERNEL32.@]
1593  * 
1594  * Copy character to consecutive cells in the console screen buffer.
1595  *
1596  * PARAMS
1597  *    hConsoleOutput    [I] Handle to screen buffer
1598  *    str               [I] Pointer to buffer with chars to write
1599  *    length            [I] Number of cells to write to
1600  *    coord             [I] Coords of first cell
1601  *    lpNumCharsWritten [O] Pointer to number of cells written
1602  *
1603  * RETURNS
1604  *    Success: TRUE
1605  *    Failure: FALSE
1606  *
1607  */
1608 BOOL WINAPI WriteConsoleOutputCharacterW( HANDLE hConsoleOutput, LPCWSTR str, DWORD length,
1609                                           COORD coord, LPDWORD lpNumCharsWritten )
1610 {
1611     BOOL ret;
1612
1613     TRACE("(%p,%s,%d,%dx%d,%p)\n", hConsoleOutput,
1614           debugstr_wn(str, length), length, coord.X, coord.Y, lpNumCharsWritten);
1615
1616     SERVER_START_REQ( write_console_output )
1617     {
1618         req->handle = console_handle_unmap(hConsoleOutput);
1619         req->x      = coord.X;
1620         req->y      = coord.Y;
1621         req->mode   = CHAR_INFO_MODE_TEXT;
1622         req->wrap   = TRUE;
1623         wine_server_add_data( req, str, length * sizeof(WCHAR) );
1624         if ((ret = !wine_server_call_err( req )))
1625         {
1626             if (lpNumCharsWritten) *lpNumCharsWritten = reply->written;
1627         }
1628     }
1629     SERVER_END_REQ;
1630     return ret;
1631 }
1632
1633
1634 /******************************************************************************
1635  * SetConsoleTitleW [KERNEL32.@]  Sets title bar string for console
1636  *
1637  * PARAMS
1638  *    title [I] Address of new title
1639  *
1640  * RETURNS
1641  *    Success: TRUE
1642  *    Failure: FALSE
1643  */
1644 BOOL WINAPI SetConsoleTitleW(LPCWSTR title)
1645 {
1646     BOOL ret;
1647
1648     TRACE("(%s)\n", debugstr_w(title));
1649     SERVER_START_REQ( set_console_input_info )
1650     {
1651         req->handle = 0;
1652         req->mask = SET_CONSOLE_INPUT_INFO_TITLE;
1653         wine_server_add_data( req, title, strlenW(title) * sizeof(WCHAR) );
1654         ret = !wine_server_call_err( req );
1655     }
1656     SERVER_END_REQ;
1657     return ret;
1658 }
1659
1660
1661 /***********************************************************************
1662  *            GetNumberOfConsoleMouseButtons   (KERNEL32.@)
1663  */
1664 BOOL WINAPI GetNumberOfConsoleMouseButtons(LPDWORD nrofbuttons)
1665 {
1666     FIXME("(%p): stub\n", nrofbuttons);
1667     *nrofbuttons = 2;
1668     return TRUE;
1669 }
1670
1671 /******************************************************************************
1672  *  SetConsoleInputExeNameW      [KERNEL32.@]
1673  */
1674 BOOL WINAPI SetConsoleInputExeNameW(LPCWSTR name)
1675 {
1676     TRACE("(%s)\n", debugstr_w(name));
1677
1678     if (!name || !name[0])
1679     {
1680         SetLastError(ERROR_INVALID_PARAMETER);
1681         return FALSE;
1682     }
1683
1684     RtlEnterCriticalSection(&CONSOLE_CritSect);
1685     if (strlenW(name) < sizeof(input_exe)/sizeof(WCHAR)) strcpyW(input_exe, name);
1686     RtlLeaveCriticalSection(&CONSOLE_CritSect);
1687
1688     return TRUE;
1689 }
1690
1691 /******************************************************************************
1692  *  SetConsoleInputExeNameA      [KERNEL32.@]
1693  */
1694 BOOL WINAPI SetConsoleInputExeNameA(LPCSTR name)
1695 {
1696     int len;
1697     LPWSTR nameW;
1698     BOOL ret;
1699
1700     if (!name || !name[0])
1701     {
1702         SetLastError(ERROR_INVALID_PARAMETER);
1703         return FALSE;
1704     }
1705
1706     len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0);
1707     if (!(nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)))) return FALSE;
1708
1709     MultiByteToWideChar(CP_ACP, 0, name, -1, nameW, len);
1710     ret = SetConsoleInputExeNameW(nameW);
1711     HeapFree(GetProcessHeap(), 0, nameW);
1712
1713     return ret;
1714 }
1715
1716 /******************************************************************
1717  *              CONSOLE_DefaultHandler
1718  *
1719  * Final control event handler
1720  */
1721 static BOOL WINAPI CONSOLE_DefaultHandler(DWORD dwCtrlType)
1722 {
1723     FIXME("Terminating process %x on event %x\n", GetCurrentProcessId(), dwCtrlType);
1724     ExitProcess(0);
1725     /* should never go here */
1726     return TRUE;
1727 }
1728
1729 /******************************************************************************
1730  * SetConsoleCtrlHandler [KERNEL32.@]  Adds function to calling process list
1731  *
1732  * PARAMS
1733  *    func [I] Address of handler function
1734  *    add  [I] Handler to add or remove
1735  *
1736  * RETURNS
1737  *    Success: TRUE
1738  *    Failure: FALSE
1739  */
1740
1741 struct ConsoleHandler
1742 {
1743     PHANDLER_ROUTINE            handler;
1744     struct ConsoleHandler*      next;
1745 };
1746
1747 static struct ConsoleHandler    CONSOLE_DefaultConsoleHandler = {CONSOLE_DefaultHandler, NULL};
1748 static struct ConsoleHandler*   CONSOLE_Handlers = &CONSOLE_DefaultConsoleHandler;
1749
1750 /*****************************************************************************/
1751
1752 /******************************************************************
1753  *              SetConsoleCtrlHandler (KERNEL32.@)
1754  */
1755 BOOL WINAPI SetConsoleCtrlHandler(PHANDLER_ROUTINE func, BOOL add)
1756 {
1757     BOOL        ret = TRUE;
1758
1759     TRACE("(%p,%i)\n", func, add);
1760
1761     if (!func)
1762     {
1763         RtlEnterCriticalSection(&CONSOLE_CritSect);
1764         if (add)
1765             NtCurrentTeb()->Peb->ProcessParameters->ConsoleFlags |= 1;
1766         else
1767             NtCurrentTeb()->Peb->ProcessParameters->ConsoleFlags &= ~1;
1768         RtlLeaveCriticalSection(&CONSOLE_CritSect);
1769     }
1770     else if (add)
1771     {
1772         struct ConsoleHandler*  ch = HeapAlloc(GetProcessHeap(), 0, sizeof(struct ConsoleHandler));
1773
1774         if (!ch) return FALSE;
1775         ch->handler = func;
1776         RtlEnterCriticalSection(&CONSOLE_CritSect);
1777         ch->next = CONSOLE_Handlers;
1778         CONSOLE_Handlers = ch;
1779         RtlLeaveCriticalSection(&CONSOLE_CritSect);
1780     }
1781     else
1782     {
1783         struct ConsoleHandler**  ch;
1784         RtlEnterCriticalSection(&CONSOLE_CritSect);
1785         for (ch = &CONSOLE_Handlers; *ch; ch = &(*ch)->next)
1786         {
1787             if ((*ch)->handler == func) break;
1788         }
1789         if (*ch)
1790         {
1791             struct ConsoleHandler*   rch = *ch;
1792
1793             /* sanity check */
1794             if (rch == &CONSOLE_DefaultConsoleHandler)
1795             {
1796                 ERR("Who's trying to remove default handler???\n");
1797                 SetLastError(ERROR_INVALID_PARAMETER);
1798                 ret = FALSE;
1799             }
1800             else
1801             {
1802                 *ch = rch->next;
1803                 HeapFree(GetProcessHeap(), 0, rch);
1804             }
1805         }
1806         else
1807         {
1808             WARN("Attempt to remove non-installed CtrlHandler %p\n", func);
1809             SetLastError(ERROR_INVALID_PARAMETER);
1810             ret = FALSE;
1811         }
1812         RtlLeaveCriticalSection(&CONSOLE_CritSect);
1813     }
1814     return ret;
1815 }
1816
1817 static LONG WINAPI CONSOLE_CtrlEventHandler(EXCEPTION_POINTERS *eptr)
1818 {
1819     TRACE("(%x)\n", eptr->ExceptionRecord->ExceptionCode);
1820     return EXCEPTION_EXECUTE_HANDLER;
1821 }
1822
1823 /******************************************************************
1824  *              CONSOLE_SendEventThread
1825  *
1826  * Internal helper to pass an event to the list on installed handlers
1827  */
1828 static DWORD WINAPI CONSOLE_SendEventThread(void* pmt)
1829 {
1830     DWORD_PTR                   event = (DWORD_PTR)pmt;
1831     struct ConsoleHandler*      ch;
1832
1833     if (event == CTRL_C_EVENT)
1834     {
1835         BOOL    caught_by_dbg = TRUE;
1836         /* First, try to pass the ctrl-C event to the debugger (if any)
1837          * If it continues, there's nothing more to do
1838          * Otherwise, we need to send the ctrl-C event to the handlers
1839          */
1840         __TRY
1841         {
1842             RaiseException( DBG_CONTROL_C, 0, 0, NULL );
1843         }
1844         __EXCEPT(CONSOLE_CtrlEventHandler)
1845         {
1846             caught_by_dbg = FALSE;
1847         }
1848         __ENDTRY;
1849         if (caught_by_dbg) return 0;
1850         /* the debugger didn't continue... so, pass to ctrl handlers */
1851     }
1852     RtlEnterCriticalSection(&CONSOLE_CritSect);
1853     for (ch = CONSOLE_Handlers; ch; ch = ch->next)
1854     {
1855         if (ch->handler(event)) break;
1856     }
1857     RtlLeaveCriticalSection(&CONSOLE_CritSect);
1858     return 1;
1859 }
1860
1861 /******************************************************************
1862  *              CONSOLE_HandleCtrlC
1863  *
1864  * Check whether the shall manipulate CtrlC events
1865  */
1866 int     CONSOLE_HandleCtrlC(unsigned sig)
1867 {
1868     /* FIXME: better test whether a console is attached to this process ??? */
1869     extern    unsigned CONSOLE_GetNumHistoryEntries(void);
1870     if (CONSOLE_GetNumHistoryEntries() == (unsigned)-1) return 0;
1871
1872     /* check if we have to ignore ctrl-C events */
1873     if (!(NtCurrentTeb()->Peb->ProcessParameters->ConsoleFlags & 1))
1874     {
1875         /* Create a separate thread to signal all the events. 
1876          * This is needed because:
1877          *  - this function can be called in an Unix signal handler (hence on an
1878          *    different stack than the thread that's running). This breaks the 
1879          *    Win32 exception mechanisms (where the thread's stack is checked).
1880          *  - since the current thread, while processing the signal, can hold the
1881          *    console critical section, we need another execution environment where
1882          *    we can wait on this critical section 
1883          */
1884         CreateThread(NULL, 0, CONSOLE_SendEventThread, (void*)CTRL_C_EVENT, 0, NULL);
1885     }
1886     return 1;
1887 }
1888
1889 /******************************************************************************
1890  * GenerateConsoleCtrlEvent [KERNEL32.@] Simulate a CTRL-C or CTRL-BREAK
1891  *
1892  * PARAMS
1893  *    dwCtrlEvent        [I] Type of event
1894  *    dwProcessGroupID   [I] Process group ID to send event to
1895  *
1896  * RETURNS
1897  *    Success: True
1898  *    Failure: False (and *should* [but doesn't] set LastError)
1899  */
1900 BOOL WINAPI GenerateConsoleCtrlEvent(DWORD dwCtrlEvent,
1901                                      DWORD dwProcessGroupID)
1902 {
1903     BOOL ret;
1904
1905     TRACE("(%d, %d)\n", dwCtrlEvent, dwProcessGroupID);
1906
1907     if (dwCtrlEvent != CTRL_C_EVENT && dwCtrlEvent != CTRL_BREAK_EVENT)
1908     {
1909         ERR("Invalid event %d for PGID %d\n", dwCtrlEvent, dwProcessGroupID);
1910         return FALSE;
1911     }
1912
1913     SERVER_START_REQ( send_console_signal )
1914     {
1915         req->signal = dwCtrlEvent;
1916         req->group_id = dwProcessGroupID;
1917         ret = !wine_server_call_err( req );
1918     }
1919     SERVER_END_REQ;
1920
1921     /* FIXME: Shall this function be synchronous, i.e., only return when all events
1922      * have been handled by all processes in the given group?
1923      * As of today, we don't wait...
1924      */
1925     return ret;
1926 }
1927
1928
1929 /******************************************************************************
1930  * CreateConsoleScreenBuffer [KERNEL32.@]  Creates a console screen buffer
1931  *
1932  * PARAMS
1933  *    dwDesiredAccess    [I] Access flag
1934  *    dwShareMode        [I] Buffer share mode
1935  *    sa                 [I] Security attributes
1936  *    dwFlags            [I] Type of buffer to create
1937  *    lpScreenBufferData [I] Reserved
1938  *
1939  * NOTES
1940  *    Should call SetLastError
1941  *
1942  * RETURNS
1943  *    Success: Handle to new console screen buffer
1944  *    Failure: INVALID_HANDLE_VALUE
1945  */
1946 HANDLE WINAPI CreateConsoleScreenBuffer(DWORD dwDesiredAccess, DWORD dwShareMode,
1947                                         LPSECURITY_ATTRIBUTES sa, DWORD dwFlags,
1948                                         LPVOID lpScreenBufferData)
1949 {
1950     HANDLE      ret = INVALID_HANDLE_VALUE;
1951
1952     TRACE("(%d,%d,%p,%d,%p)\n",
1953           dwDesiredAccess, dwShareMode, sa, dwFlags, lpScreenBufferData);
1954
1955     if (dwFlags != CONSOLE_TEXTMODE_BUFFER || lpScreenBufferData != NULL)
1956     {
1957         SetLastError(ERROR_INVALID_PARAMETER);
1958         return INVALID_HANDLE_VALUE;
1959     }
1960
1961     SERVER_START_REQ(create_console_output)
1962     {
1963         req->handle_in  = 0;
1964         req->access     = dwDesiredAccess;
1965         req->attributes = (sa && sa->bInheritHandle) ? OBJ_INHERIT : 0;
1966         req->share      = dwShareMode;
1967         req->fd         = -1;
1968         if (!wine_server_call_err( req ))
1969             ret = console_handle_map( wine_server_ptr_handle( reply->handle_out ));
1970     }
1971     SERVER_END_REQ;
1972
1973     return ret;
1974 }
1975
1976
1977 /***********************************************************************
1978  *           GetConsoleScreenBufferInfo   (KERNEL32.@)
1979  */
1980 BOOL WINAPI GetConsoleScreenBufferInfo(HANDLE hConsoleOutput, LPCONSOLE_SCREEN_BUFFER_INFO csbi)
1981 {
1982     BOOL        ret;
1983
1984     SERVER_START_REQ(get_console_output_info)
1985     {
1986         req->handle = console_handle_unmap(hConsoleOutput);
1987         if ((ret = !wine_server_call_err( req )))
1988         {
1989             csbi->dwSize.X              = reply->width;
1990             csbi->dwSize.Y              = reply->height;
1991             csbi->dwCursorPosition.X    = reply->cursor_x;
1992             csbi->dwCursorPosition.Y    = reply->cursor_y;
1993             csbi->wAttributes           = reply->attr;
1994             csbi->srWindow.Left         = reply->win_left;
1995             csbi->srWindow.Right        = reply->win_right;
1996             csbi->srWindow.Top          = reply->win_top;
1997             csbi->srWindow.Bottom       = reply->win_bottom;
1998             csbi->dwMaximumWindowSize.X = reply->max_width;
1999             csbi->dwMaximumWindowSize.Y = reply->max_height;
2000         }
2001     }
2002     SERVER_END_REQ;
2003
2004     TRACE("(%p,(%d,%d) (%d,%d) %d (%d,%d-%d,%d) (%d,%d)\n", 
2005           hConsoleOutput, csbi->dwSize.X, csbi->dwSize.Y,
2006           csbi->dwCursorPosition.X, csbi->dwCursorPosition.Y,
2007           csbi->wAttributes,
2008           csbi->srWindow.Left, csbi->srWindow.Top, csbi->srWindow.Right, csbi->srWindow.Bottom,
2009           csbi->dwMaximumWindowSize.X, csbi->dwMaximumWindowSize.Y);
2010
2011     return ret;
2012 }
2013
2014
2015 /******************************************************************************
2016  * SetConsoleActiveScreenBuffer [KERNEL32.@]  Sets buffer to current console
2017  *
2018  * RETURNS
2019  *    Success: TRUE
2020  *    Failure: FALSE
2021  */
2022 BOOL WINAPI SetConsoleActiveScreenBuffer(HANDLE hConsoleOutput)
2023 {
2024     BOOL ret;
2025
2026     TRACE("(%p)\n", hConsoleOutput);
2027
2028     SERVER_START_REQ( set_console_input_info )
2029     {
2030         req->handle    = 0;
2031         req->mask      = SET_CONSOLE_INPUT_INFO_ACTIVE_SB;
2032         req->active_sb = wine_server_obj_handle( hConsoleOutput );
2033         ret = !wine_server_call_err( req );
2034     }
2035     SERVER_END_REQ;
2036     return ret;
2037 }
2038
2039
2040 /***********************************************************************
2041  *            GetConsoleMode   (KERNEL32.@)
2042  */
2043 BOOL WINAPI GetConsoleMode(HANDLE hcon, LPDWORD mode)
2044 {
2045     return get_console_mode(hcon, mode, NULL);
2046 }
2047
2048
2049 /******************************************************************************
2050  * SetConsoleMode [KERNEL32.@]  Sets input mode of console's input buffer
2051  *
2052  * PARAMS
2053  *    hcon [I] Handle to console input or screen buffer
2054  *    mode [I] Input or output mode to set
2055  *
2056  * RETURNS
2057  *    Success: TRUE
2058  *    Failure: FALSE
2059  *
2060  *    mode:
2061  *      ENABLE_PROCESSED_INPUT  0x01
2062  *      ENABLE_LINE_INPUT       0x02
2063  *      ENABLE_ECHO_INPUT       0x04
2064  *      ENABLE_WINDOW_INPUT     0x08
2065  *      ENABLE_MOUSE_INPUT      0x10
2066  */
2067 BOOL WINAPI SetConsoleMode(HANDLE hcon, DWORD mode)
2068 {
2069     BOOL ret;
2070
2071     SERVER_START_REQ(set_console_mode)
2072     {
2073         req->handle = console_handle_unmap(hcon);
2074         req->mode = mode;
2075         ret = !wine_server_call_err( req );
2076     }
2077     SERVER_END_REQ;
2078     /* FIXME: when resetting a console input to editline mode, I think we should
2079      * empty the S_EditString buffer
2080      */
2081
2082     TRACE("(%p,%x) retval == %d\n", hcon, mode, ret);
2083
2084     return ret;
2085 }
2086
2087
2088 /******************************************************************
2089  *              CONSOLE_WriteChars
2090  *
2091  * WriteConsoleOutput helper: hides server call semantics
2092  * writes a string at a given pos with standard attribute
2093  */
2094 static int CONSOLE_WriteChars(HANDLE hCon, LPCWSTR lpBuffer, int nc, COORD* pos)
2095 {
2096     int written = -1;
2097
2098     if (!nc) return 0;
2099
2100     SERVER_START_REQ( write_console_output )
2101     {
2102         req->handle = console_handle_unmap(hCon);
2103         req->x      = pos->X;
2104         req->y      = pos->Y;
2105         req->mode   = CHAR_INFO_MODE_TEXTSTDATTR;
2106         req->wrap   = FALSE;
2107         wine_server_add_data( req, lpBuffer, nc * sizeof(WCHAR) );
2108         if (!wine_server_call_err( req )) written = reply->written;
2109     }
2110     SERVER_END_REQ;
2111
2112     if (written > 0) pos->X += written;
2113     return written;
2114 }
2115
2116 /******************************************************************
2117  *              next_line
2118  *
2119  * WriteConsoleOutput helper: handles passing to next line (+scrolling if necessary)
2120  *
2121  */
2122 static int      next_line(HANDLE hCon, CONSOLE_SCREEN_BUFFER_INFO* csbi)
2123 {
2124     SMALL_RECT  src;
2125     CHAR_INFO   ci;
2126     COORD       dst;
2127
2128     csbi->dwCursorPosition.X = 0;
2129     csbi->dwCursorPosition.Y++;
2130
2131     if (csbi->dwCursorPosition.Y < csbi->dwSize.Y) return 1;
2132
2133     src.Top    = 1;
2134     src.Bottom = csbi->dwSize.Y - 1;
2135     src.Left   = 0;
2136     src.Right  = csbi->dwSize.X - 1;
2137
2138     dst.X      = 0;
2139     dst.Y      = 0;
2140
2141     ci.Attributes = csbi->wAttributes;
2142     ci.Char.UnicodeChar = ' ';
2143
2144     csbi->dwCursorPosition.Y--;
2145     if (!ScrollConsoleScreenBufferW(hCon, &src, NULL, dst, &ci))
2146         return 0;
2147     return 1;
2148 }
2149
2150 /******************************************************************
2151  *              write_block
2152  *
2153  * WriteConsoleOutput helper: writes a block of non special characters
2154  * Block can spread on several lines, and wrapping, if needed, is
2155  * handled
2156  *
2157  */
2158 static int      write_block(HANDLE hCon, CONSOLE_SCREEN_BUFFER_INFO* csbi,
2159                             DWORD mode, LPCWSTR ptr, int len)
2160 {
2161     int blk;    /* number of chars to write on current line */
2162     int done;   /* number of chars already written */
2163
2164     if (len <= 0) return 1;
2165
2166     if (mode & ENABLE_WRAP_AT_EOL_OUTPUT) /* writes remaining on next line */
2167     {
2168         for (done = 0; done < len; done += blk)
2169         {
2170             blk = min(len - done, csbi->dwSize.X - csbi->dwCursorPosition.X);
2171
2172             if (CONSOLE_WriteChars(hCon, ptr + done, blk, &csbi->dwCursorPosition) != blk)
2173                 return 0;
2174             if (csbi->dwCursorPosition.X == csbi->dwSize.X && !next_line(hCon, csbi))
2175                 return 0;
2176         }
2177     }
2178     else
2179     {
2180         int     pos = csbi->dwCursorPosition.X;
2181         /* FIXME: we could reduce the number of loops
2182          * but, in most cases we wouldn't gain lots of time (it would only
2183          * happen if we're asked to overwrite more than twice the part of the line,
2184          * which is unlikely
2185          */
2186         for (blk = done = 0; done < len; done += blk)
2187         {
2188             blk = min(len - done, csbi->dwSize.X - csbi->dwCursorPosition.X);
2189
2190             csbi->dwCursorPosition.X = pos;
2191             if (CONSOLE_WriteChars(hCon, ptr + done, blk, &csbi->dwCursorPosition) != blk)
2192                 return 0;
2193         }
2194     }
2195
2196     return 1;
2197 }
2198
2199 /***********************************************************************
2200  *            WriteConsoleW   (KERNEL32.@)
2201  */
2202 BOOL WINAPI WriteConsoleW(HANDLE hConsoleOutput, LPCVOID lpBuffer, DWORD nNumberOfCharsToWrite,
2203                           LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved)
2204 {
2205     DWORD                       mode;
2206     DWORD                       nw = 0;
2207     const WCHAR*                psz = lpBuffer;
2208     CONSOLE_SCREEN_BUFFER_INFO  csbi;
2209     int                         k, first = 0;
2210     BOOL                        bare;
2211
2212     TRACE("%p %s %d %p %p\n",
2213           hConsoleOutput, debugstr_wn(lpBuffer, nNumberOfCharsToWrite),
2214           nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved);
2215
2216     if (lpNumberOfCharsWritten) *lpNumberOfCharsWritten = 0;
2217
2218     if (!get_console_mode(hConsoleOutput, &mode, &bare)) return FALSE;
2219
2220     if (bare)
2221     {
2222         char*           ptr;
2223         unsigned        len;
2224         BOOL            ret;
2225
2226         /* FIXME: mode ENABLED_OUTPUT is not processed (or actually we rely on underlying Unix/TTY fd
2227          * to do the job
2228          */
2229         len = WideCharToMultiByte(CP_UNIXCP, 0, lpBuffer, nNumberOfCharsToWrite, NULL, 0, NULL, NULL);
2230         if ((ptr = HeapAlloc(GetProcessHeap(), 0, len)) == NULL)
2231             return FALSE;
2232
2233         WideCharToMultiByte(CP_UNIXCP, 0, lpBuffer, nNumberOfCharsToWrite, ptr, len, NULL, NULL);
2234         ret = WriteFile(wine_server_ptr_handle(console_handle_unmap(hConsoleOutput)),
2235                         ptr, len, lpNumberOfCharsWritten, NULL);
2236         if (ret && lpNumberOfCharsWritten)
2237         {
2238             if (*lpNumberOfCharsWritten == len)
2239                 *lpNumberOfCharsWritten = nNumberOfCharsToWrite;
2240             else
2241                 FIXME("Conversion not supported yet\n");
2242         }
2243         HeapFree(GetProcessHeap(), 0, ptr);
2244         return ret;
2245     }
2246
2247     if (!GetConsoleScreenBufferInfo(hConsoleOutput, &csbi))
2248         return FALSE;
2249
2250     if (!nNumberOfCharsToWrite) return TRUE;
2251
2252     if (mode & ENABLE_PROCESSED_OUTPUT)
2253     {
2254         unsigned int    i;
2255
2256         for (i = 0; i < nNumberOfCharsToWrite; i++)
2257         {
2258             switch (psz[i])
2259             {
2260             case '\b': case '\t': case '\n': case '\a': case '\r':
2261                 /* don't handle here the i-th char... done below */
2262                 if ((k = i - first) > 0)
2263                 {
2264                     if (!write_block(hConsoleOutput, &csbi, mode, &psz[first], k))
2265                         goto the_end;
2266                     nw += k;
2267                 }
2268                 first = i + 1;
2269                 nw++;
2270             }
2271             switch (psz[i])
2272             {
2273             case '\b':
2274                 if (csbi.dwCursorPosition.X > 0) csbi.dwCursorPosition.X--;
2275                 break;
2276             case '\t':
2277                 {
2278                     WCHAR tmp[8] = {' ',' ',' ',' ',' ',' ',' ',' '};
2279
2280                     if (!write_block(hConsoleOutput, &csbi, mode, tmp,
2281                                      ((csbi.dwCursorPosition.X + 8) & ~7) - csbi.dwCursorPosition.X))
2282                         goto the_end;
2283                 }
2284                 break;
2285             case '\n':
2286                 next_line(hConsoleOutput, &csbi);
2287                 break;
2288             case '\a':
2289                 Beep(400, 300);
2290                 break;
2291             case '\r':
2292                 csbi.dwCursorPosition.X = 0;
2293                 break;
2294             default:
2295                 break;
2296             }
2297         }
2298     }
2299
2300     /* write the remaining block (if any) if processed output is enabled, or the
2301      * entire buffer otherwise
2302      */
2303     if ((k = nNumberOfCharsToWrite - first) > 0)
2304     {
2305         if (!write_block(hConsoleOutput, &csbi, mode, &psz[first], k))
2306             goto the_end;
2307         nw += k;
2308     }
2309
2310  the_end:
2311     SetConsoleCursorPosition(hConsoleOutput, csbi.dwCursorPosition);
2312     if (lpNumberOfCharsWritten) *lpNumberOfCharsWritten = nw;
2313     return nw != 0;
2314 }
2315
2316
2317 /***********************************************************************
2318  *            WriteConsoleA   (KERNEL32.@)
2319  */
2320 BOOL WINAPI WriteConsoleA(HANDLE hConsoleOutput, LPCVOID lpBuffer, DWORD nNumberOfCharsToWrite,
2321                           LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved)
2322 {
2323     BOOL        ret;
2324     LPWSTR      xstring;
2325     DWORD       n;
2326
2327     n = MultiByteToWideChar(GetConsoleOutputCP(), 0, lpBuffer, nNumberOfCharsToWrite, NULL, 0);
2328
2329     if (lpNumberOfCharsWritten) *lpNumberOfCharsWritten = 0;
2330     xstring = HeapAlloc(GetProcessHeap(), 0, n * sizeof(WCHAR));
2331     if (!xstring) return 0;
2332
2333     MultiByteToWideChar(GetConsoleOutputCP(), 0, lpBuffer, nNumberOfCharsToWrite, xstring, n);
2334
2335     ret = WriteConsoleW(hConsoleOutput, xstring, n, lpNumberOfCharsWritten, 0);
2336
2337     HeapFree(GetProcessHeap(), 0, xstring);
2338
2339     return ret;
2340 }
2341
2342 /******************************************************************************
2343  * SetConsoleCursorPosition [KERNEL32.@]
2344  * Sets the cursor position in console
2345  *
2346  * PARAMS
2347  *    hConsoleOutput   [I] Handle of console screen buffer
2348  *    dwCursorPosition [I] New cursor position coordinates
2349  *
2350  * RETURNS
2351  *    Success: TRUE
2352  *    Failure: FALSE
2353  */
2354 BOOL WINAPI SetConsoleCursorPosition(HANDLE hcon, COORD pos)
2355 {
2356     BOOL                        ret;
2357     CONSOLE_SCREEN_BUFFER_INFO  csbi;
2358     int                         do_move = 0;
2359     int                         w, h;
2360
2361     TRACE("%p %d %d\n", hcon, pos.X, pos.Y);
2362
2363     SERVER_START_REQ(set_console_output_info)
2364     {
2365         req->handle         = console_handle_unmap(hcon);
2366         req->cursor_x       = pos.X;
2367         req->cursor_y       = pos.Y;
2368         req->mask           = SET_CONSOLE_OUTPUT_INFO_CURSOR_POS;
2369         ret = !wine_server_call_err( req );
2370     }
2371     SERVER_END_REQ;
2372
2373     if (!ret || !GetConsoleScreenBufferInfo(hcon, &csbi))
2374         return FALSE;
2375
2376     /* if cursor is no longer visible, scroll the visible window... */
2377     w = csbi.srWindow.Right - csbi.srWindow.Left + 1;
2378     h = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
2379     if (pos.X < csbi.srWindow.Left)
2380     {
2381         csbi.srWindow.Left   = min(pos.X, csbi.dwSize.X - w);
2382         do_move++;
2383     }
2384     else if (pos.X > csbi.srWindow.Right)
2385     {
2386         csbi.srWindow.Left   = max(pos.X, w) - w + 1;
2387         do_move++;
2388     }
2389     csbi.srWindow.Right  = csbi.srWindow.Left + w - 1;
2390
2391     if (pos.Y < csbi.srWindow.Top)
2392     {
2393         csbi.srWindow.Top    = min(pos.Y, csbi.dwSize.Y - h);
2394         do_move++;
2395     }
2396     else if (pos.Y > csbi.srWindow.Bottom)
2397     {
2398         csbi.srWindow.Top   = max(pos.Y, h) - h + 1;
2399         do_move++;
2400     }
2401     csbi.srWindow.Bottom = csbi.srWindow.Top + h - 1;
2402
2403     ret = (do_move) ? SetConsoleWindowInfo(hcon, TRUE, &csbi.srWindow) : TRUE;
2404
2405     return ret;
2406 }
2407
2408 /******************************************************************************
2409  * GetConsoleCursorInfo [KERNEL32.@]  Gets size and visibility of console
2410  *
2411  * PARAMS
2412  *    hcon  [I] Handle to console screen buffer
2413  *    cinfo [O] Address of cursor information
2414  *
2415  * RETURNS
2416  *    Success: TRUE
2417  *    Failure: FALSE
2418  */
2419 BOOL WINAPI GetConsoleCursorInfo(HANDLE hCon, LPCONSOLE_CURSOR_INFO cinfo)
2420 {
2421     BOOL ret;
2422
2423     SERVER_START_REQ(get_console_output_info)
2424     {
2425         req->handle = console_handle_unmap(hCon);
2426         ret = !wine_server_call_err( req );
2427         if (ret && cinfo)
2428         {
2429             cinfo->dwSize = reply->cursor_size;
2430             cinfo->bVisible = reply->cursor_visible;
2431         }
2432     }
2433     SERVER_END_REQ;
2434
2435     if (!ret) return FALSE;
2436
2437     if (!cinfo)
2438     {
2439         SetLastError(ERROR_INVALID_ACCESS);
2440         ret = FALSE;
2441     }
2442     else TRACE("(%p) returning (%d,%d)\n", hCon, cinfo->dwSize, cinfo->bVisible);
2443
2444     return ret;
2445 }
2446
2447
2448 /******************************************************************************
2449  * SetConsoleCursorInfo [KERNEL32.@]  Sets size and visibility of cursor
2450  *
2451  * PARAMS
2452  *      hcon    [I] Handle to console screen buffer
2453  *      cinfo   [I] Address of cursor information
2454  * RETURNS
2455  *    Success: TRUE
2456  *    Failure: FALSE
2457  */
2458 BOOL WINAPI SetConsoleCursorInfo(HANDLE hCon, LPCONSOLE_CURSOR_INFO cinfo)
2459 {
2460     BOOL ret;
2461
2462     TRACE("(%p,%d,%d)\n", hCon, cinfo->dwSize, cinfo->bVisible);
2463     SERVER_START_REQ(set_console_output_info)
2464     {
2465         req->handle         = console_handle_unmap(hCon);
2466         req->cursor_size    = cinfo->dwSize;
2467         req->cursor_visible = cinfo->bVisible;
2468         req->mask           = SET_CONSOLE_OUTPUT_INFO_CURSOR_GEOM;
2469         ret = !wine_server_call_err( req );
2470     }
2471     SERVER_END_REQ;
2472     return ret;
2473 }
2474
2475
2476 /******************************************************************************
2477  * SetConsoleWindowInfo [KERNEL32.@]  Sets size and position of console
2478  *
2479  * PARAMS
2480  *      hcon            [I] Handle to console screen buffer
2481  *      bAbsolute       [I] Coordinate type flag
2482  *      window          [I] Address of new window rectangle
2483  * RETURNS
2484  *    Success: TRUE
2485  *    Failure: FALSE
2486  */
2487 BOOL WINAPI SetConsoleWindowInfo(HANDLE hCon, BOOL bAbsolute, LPSMALL_RECT window)
2488 {
2489     SMALL_RECT  p = *window;
2490     BOOL        ret;
2491
2492     TRACE("(%p,%d,(%d,%d-%d,%d))\n", hCon, bAbsolute, p.Left, p.Top, p.Right, p.Bottom);
2493
2494     if (!bAbsolute)
2495     {
2496         CONSOLE_SCREEN_BUFFER_INFO      csbi;
2497
2498         if (!GetConsoleScreenBufferInfo(hCon, &csbi))
2499             return FALSE;
2500         p.Left   += csbi.srWindow.Left;
2501         p.Top    += csbi.srWindow.Top;
2502         p.Right  += csbi.srWindow.Right;
2503         p.Bottom += csbi.srWindow.Bottom;
2504     }
2505     SERVER_START_REQ(set_console_output_info)
2506     {
2507         req->handle         = console_handle_unmap(hCon);
2508         req->win_left       = p.Left;
2509         req->win_top        = p.Top;
2510         req->win_right      = p.Right;
2511         req->win_bottom     = p.Bottom;
2512         req->mask           = SET_CONSOLE_OUTPUT_INFO_DISPLAY_WINDOW;
2513         ret = !wine_server_call_err( req );
2514     }
2515     SERVER_END_REQ;
2516
2517     return ret;
2518 }
2519
2520
2521 /******************************************************************************
2522  * SetConsoleTextAttribute [KERNEL32.@]  Sets colors for text
2523  *
2524  * Sets the foreground and background color attributes of characters
2525  * written to the screen buffer.
2526  *
2527  * RETURNS
2528  *    Success: TRUE
2529  *    Failure: FALSE
2530  */
2531 BOOL WINAPI SetConsoleTextAttribute(HANDLE hConsoleOutput, WORD wAttr)
2532 {
2533     BOOL ret;
2534
2535     TRACE("(%p,%d)\n", hConsoleOutput, wAttr);
2536     SERVER_START_REQ(set_console_output_info)
2537     {
2538         req->handle = console_handle_unmap(hConsoleOutput);
2539         req->attr   = wAttr;
2540         req->mask   = SET_CONSOLE_OUTPUT_INFO_ATTR;
2541         ret = !wine_server_call_err( req );
2542     }
2543     SERVER_END_REQ;
2544     return ret;
2545 }
2546
2547
2548 /******************************************************************************
2549  * SetConsoleScreenBufferSize [KERNEL32.@]  Changes size of console
2550  *
2551  * PARAMS
2552  *    hConsoleOutput [I] Handle to console screen buffer
2553  *    dwSize         [I] New size in character rows and cols
2554  *
2555  * RETURNS
2556  *    Success: TRUE
2557  *    Failure: FALSE
2558  */
2559 BOOL WINAPI SetConsoleScreenBufferSize(HANDLE hConsoleOutput, COORD dwSize)
2560 {
2561     BOOL ret;
2562
2563     TRACE("(%p,(%d,%d))\n", hConsoleOutput, dwSize.X, dwSize.Y);
2564     SERVER_START_REQ(set_console_output_info)
2565     {
2566         req->handle = console_handle_unmap(hConsoleOutput);
2567         req->width  = dwSize.X;
2568         req->height = dwSize.Y;
2569         req->mask   = SET_CONSOLE_OUTPUT_INFO_SIZE;
2570         ret = !wine_server_call_err( req );
2571     }
2572     SERVER_END_REQ;
2573     return ret;
2574 }
2575
2576
2577 /******************************************************************************
2578  * ScrollConsoleScreenBufferA [KERNEL32.@]
2579  *
2580  */
2581 BOOL WINAPI ScrollConsoleScreenBufferA(HANDLE hConsoleOutput, LPSMALL_RECT lpScrollRect,
2582                                        LPSMALL_RECT lpClipRect, COORD dwDestOrigin,
2583                                        LPCHAR_INFO lpFill)
2584 {
2585     CHAR_INFO   ciw;
2586
2587     ciw.Attributes = lpFill->Attributes;
2588     MultiByteToWideChar(GetConsoleOutputCP(), 0, &lpFill->Char.AsciiChar, 1, &ciw.Char.UnicodeChar, 1);
2589
2590     return ScrollConsoleScreenBufferW(hConsoleOutput, lpScrollRect, lpClipRect,
2591                                       dwDestOrigin, &ciw);
2592 }
2593
2594 /******************************************************************
2595  *              CONSOLE_FillLineUniform
2596  *
2597  * Helper function for ScrollConsoleScreenBufferW
2598  * Fills a part of a line with a constant character info
2599  */
2600 void CONSOLE_FillLineUniform(HANDLE hConsoleOutput, int i, int j, int len, LPCHAR_INFO lpFill)
2601 {
2602     SERVER_START_REQ( fill_console_output )
2603     {
2604         req->handle    = console_handle_unmap(hConsoleOutput);
2605         req->mode      = CHAR_INFO_MODE_TEXTATTR;
2606         req->x         = i;
2607         req->y         = j;
2608         req->count     = len;
2609         req->wrap      = FALSE;
2610         req->data.ch   = lpFill->Char.UnicodeChar;
2611         req->data.attr = lpFill->Attributes;
2612         wine_server_call_err( req );
2613     }
2614     SERVER_END_REQ;
2615 }
2616
2617 /******************************************************************************
2618  * ScrollConsoleScreenBufferW [KERNEL32.@]
2619  *
2620  */
2621
2622 BOOL WINAPI ScrollConsoleScreenBufferW(HANDLE hConsoleOutput, LPSMALL_RECT lpScrollRect,
2623                                        LPSMALL_RECT lpClipRect, COORD dwDestOrigin,
2624                                        LPCHAR_INFO lpFill)
2625 {
2626     SMALL_RECT                  dst;
2627     DWORD                       ret;
2628     int                         i, j;
2629     int                         start = -1;
2630     SMALL_RECT                  clip;
2631     CONSOLE_SCREEN_BUFFER_INFO  csbi;
2632     BOOL                        inside;
2633     COORD                       src;
2634
2635     if (lpClipRect)
2636         TRACE("(%p,(%d,%d-%d,%d),(%d,%d-%d,%d),%d-%d,%p)\n", hConsoleOutput,
2637               lpScrollRect->Left, lpScrollRect->Top,
2638               lpScrollRect->Right, lpScrollRect->Bottom,
2639               lpClipRect->Left, lpClipRect->Top,
2640               lpClipRect->Right, lpClipRect->Bottom,
2641               dwDestOrigin.X, dwDestOrigin.Y, lpFill);
2642     else
2643         TRACE("(%p,(%d,%d-%d,%d),(nil),%d-%d,%p)\n", hConsoleOutput,
2644               lpScrollRect->Left, lpScrollRect->Top,
2645               lpScrollRect->Right, lpScrollRect->Bottom,
2646               dwDestOrigin.X, dwDestOrigin.Y, lpFill);
2647
2648     if (!GetConsoleScreenBufferInfo(hConsoleOutput, &csbi))
2649         return FALSE;
2650
2651     src.X = lpScrollRect->Left;
2652     src.Y = lpScrollRect->Top;
2653
2654     /* step 1: get dst rect */
2655     dst.Left = dwDestOrigin.X;
2656     dst.Top = dwDestOrigin.Y;
2657     dst.Right = dst.Left + (lpScrollRect->Right - lpScrollRect->Left);
2658     dst.Bottom = dst.Top + (lpScrollRect->Bottom - lpScrollRect->Top);
2659
2660     /* step 2a: compute the final clip rect (optional passed clip and screen buffer limits */
2661     if (lpClipRect)
2662     {
2663         clip.Left   = max(0, lpClipRect->Left);
2664         clip.Right  = min(csbi.dwSize.X - 1, lpClipRect->Right);
2665         clip.Top    = max(0, lpClipRect->Top);
2666         clip.Bottom = min(csbi.dwSize.Y - 1, lpClipRect->Bottom);
2667     }
2668     else
2669     {
2670         clip.Left   = 0;
2671         clip.Right  = csbi.dwSize.X - 1;
2672         clip.Top    = 0;
2673         clip.Bottom = csbi.dwSize.Y - 1;
2674     }
2675     if (clip.Left > clip.Right || clip.Top > clip.Bottom) return FALSE;
2676
2677     /* step 2b: clip dst rect */
2678     if (dst.Left   < clip.Left  ) {src.X += clip.Left - dst.Left; dst.Left   = clip.Left;}
2679     if (dst.Top    < clip.Top   ) {src.Y += clip.Top  - dst.Top;  dst.Top    = clip.Top;}
2680     if (dst.Right  > clip.Right ) dst.Right  = clip.Right;
2681     if (dst.Bottom > clip.Bottom) dst.Bottom = clip.Bottom;
2682
2683     /* step 3: transfer the bits */
2684     SERVER_START_REQ(move_console_output)
2685     {
2686         req->handle = console_handle_unmap(hConsoleOutput);
2687         req->x_src = src.X;
2688         req->y_src = src.Y;
2689         req->x_dst = dst.Left;
2690         req->y_dst = dst.Top;
2691         req->w = dst.Right - dst.Left + 1;
2692         req->h = dst.Bottom - dst.Top + 1;
2693         ret = !wine_server_call_err( req );
2694     }
2695     SERVER_END_REQ;
2696
2697     if (!ret) return FALSE;
2698
2699     /* step 4: clean out the exposed part */
2700
2701     /* have to write cell [i,j] if it is not in dst rect (because it has already
2702      * been written to by the scroll) and is in clip (we shall not write
2703      * outside of clip)
2704      */
2705     for (j = max(lpScrollRect->Top, clip.Top); j <= min(lpScrollRect->Bottom, clip.Bottom); j++)
2706     {
2707         inside = dst.Top <= j && j <= dst.Bottom;
2708         start = -1;
2709         for (i = max(lpScrollRect->Left, clip.Left); i <= min(lpScrollRect->Right, clip.Right); i++)
2710         {
2711             if (inside && dst.Left <= i && i <= dst.Right)
2712             {
2713                 if (start != -1)
2714                 {
2715                     CONSOLE_FillLineUniform(hConsoleOutput, start, j, i - start, lpFill);
2716                     start = -1;
2717                 }
2718             }
2719             else
2720             {
2721                 if (start == -1) start = i;
2722             }
2723         }
2724         if (start != -1)
2725             CONSOLE_FillLineUniform(hConsoleOutput, start, j, i - start, lpFill);
2726     }
2727
2728     return TRUE;
2729 }
2730
2731 /******************************************************************
2732  *              AttachConsole  (KERNEL32.@)
2733  */
2734 BOOL WINAPI AttachConsole(DWORD dwProcessId)
2735 {
2736     FIXME("stub %x\n",dwProcessId);
2737     return TRUE;
2738 }
2739
2740 /******************************************************************
2741  *              GetConsoleDisplayMode  (KERNEL32.@)
2742  */
2743 BOOL WINAPI GetConsoleDisplayMode(LPDWORD lpModeFlags)
2744 {
2745     TRACE("semi-stub: %p\n", lpModeFlags);
2746     /* It is safe to successfully report windowed mode */
2747     *lpModeFlags = 0;
2748     return TRUE;
2749 }
2750
2751 /******************************************************************
2752  *              SetConsoleDisplayMode  (KERNEL32.@)
2753  */
2754 BOOL WINAPI SetConsoleDisplayMode(HANDLE hConsoleOutput, DWORD dwFlags,
2755                                   COORD *lpNewScreenBufferDimensions)
2756 {
2757     TRACE("(%p, %x, (%d, %d))\n", hConsoleOutput, dwFlags,
2758           lpNewScreenBufferDimensions->X, lpNewScreenBufferDimensions->Y);
2759     if (dwFlags == 1)
2760     {
2761         /* We cannot switch to fullscreen */
2762         return FALSE;
2763     }
2764     return TRUE;
2765 }
2766
2767
2768 /* ====================================================================
2769  *
2770  * Console manipulation functions
2771  *
2772  * ====================================================================*/
2773
2774 /* some missing functions...
2775  * FIXME: those are likely to be defined as undocumented function in kernel32 (or part of them)
2776  * should get the right API and implement them
2777  *      GetConsoleCommandHistory[AW] (dword dword dword)
2778  *      GetConsoleCommandHistoryLength[AW]
2779  *      SetConsoleCommandHistoryMode
2780  *      SetConsoleNumberOfCommands[AW]
2781  */
2782 int CONSOLE_GetHistory(int idx, WCHAR* buf, int buf_len)
2783 {
2784     int len = 0;
2785
2786     SERVER_START_REQ( get_console_input_history )
2787     {
2788         req->handle = 0;
2789         req->index = idx;
2790         if (buf && buf_len > 1)
2791         {
2792             wine_server_set_reply( req, buf, (buf_len - 1) * sizeof(WCHAR) );
2793         }
2794         if (!wine_server_call_err( req ))
2795         {
2796             if (buf) buf[wine_server_reply_size(reply) / sizeof(WCHAR)] = 0;
2797             len = reply->total / sizeof(WCHAR) + 1;
2798         }
2799     }
2800     SERVER_END_REQ;
2801     return len;
2802 }
2803
2804 /******************************************************************
2805  *              CONSOLE_AppendHistory
2806  *
2807  *
2808  */
2809 BOOL    CONSOLE_AppendHistory(const WCHAR* ptr)
2810 {
2811     size_t      len = strlenW(ptr);
2812     BOOL        ret;
2813
2814     while (len && (ptr[len - 1] == '\n' || ptr[len - 1] == '\r')) len--;
2815     if (!len) return FALSE;
2816
2817     SERVER_START_REQ( append_console_input_history )
2818     {
2819         req->handle = 0;
2820         wine_server_add_data( req, ptr, len * sizeof(WCHAR) );
2821         ret = !wine_server_call_err( req );
2822     }
2823     SERVER_END_REQ;
2824     return ret;
2825 }
2826
2827 /******************************************************************
2828  *              CONSOLE_GetNumHistoryEntries
2829  *
2830  *
2831  */
2832 unsigned CONSOLE_GetNumHistoryEntries(void)
2833 {
2834     unsigned ret = -1;
2835     SERVER_START_REQ(get_console_input_info)
2836     {
2837         req->handle = 0;
2838         if (!wine_server_call_err( req )) ret = reply->history_index;
2839     }
2840     SERVER_END_REQ;
2841     return ret;
2842 }
2843
2844 /******************************************************************
2845  *              CONSOLE_GetEditionMode
2846  *
2847  *
2848  */
2849 BOOL CONSOLE_GetEditionMode(HANDLE hConIn, int* mode)
2850 {
2851     unsigned ret = FALSE;
2852     SERVER_START_REQ(get_console_input_info)
2853     {
2854         req->handle = console_handle_unmap(hConIn);
2855         if ((ret = !wine_server_call_err( req )))
2856             *mode = reply->edition_mode;
2857     }
2858     SERVER_END_REQ;
2859     return ret;
2860 }
2861
2862 /******************************************************************
2863  *              GetConsoleAliasW
2864  *
2865  *
2866  * RETURNS
2867  *    0 if an error occurred, non-zero for success
2868  *
2869  */
2870 DWORD WINAPI GetConsoleAliasW(LPWSTR lpSource, LPWSTR lpTargetBuffer,
2871                               DWORD TargetBufferLength, LPWSTR lpExename)
2872 {
2873     FIXME("(%s,%p,%d,%s): stub\n", debugstr_w(lpSource), lpTargetBuffer, TargetBufferLength, debugstr_w(lpExename));
2874     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2875     return 0;
2876 }
2877
2878 /******************************************************************
2879  *              GetConsoleProcessList  (KERNEL32.@)
2880  */
2881 DWORD WINAPI GetConsoleProcessList(LPDWORD processlist, DWORD processcount)
2882 {
2883     FIXME("(%p,%d): stub\n", processlist, processcount);
2884
2885     if (!processlist || processcount < 1)
2886     {
2887         SetLastError(ERROR_INVALID_PARAMETER);
2888         return 0;
2889     }
2890
2891     return 0;
2892 }
2893
2894 BOOL CONSOLE_Init(RTL_USER_PROCESS_PARAMETERS *params)
2895 {
2896     if (params->ConsoleHandle == KERNEL32_CONSOLE_SHELL)
2897     {
2898         HANDLE  conin;
2899
2900         /* FIXME: to be done even if program is a GUI ? */
2901         /* This is wine specific: we have no parent (we're started from unix)
2902          * so, create a simple console with bare handles
2903          */
2904         wine_server_send_fd(0);
2905         SERVER_START_REQ( alloc_console )
2906         {
2907             req->access     = GENERIC_READ | GENERIC_WRITE;
2908             req->attributes = OBJ_INHERIT;
2909             req->pid        = 0xffffffff;
2910             req->input_fd   = 0;
2911             wine_server_call( req );
2912             conin = wine_server_ptr_handle( reply->handle_in );
2913             /* reply->event shouldn't be created by server */
2914         }
2915         SERVER_END_REQ;
2916
2917         if (!params->hStdInput)
2918             params->hStdInput = conin;
2919
2920         if (!params->hStdOutput)
2921         {
2922             wine_server_send_fd(1);
2923             SERVER_START_REQ( create_console_output )
2924             {
2925                 req->handle_in  = wine_server_obj_handle(conin);
2926                 req->access     = GENERIC_WRITE|GENERIC_READ;
2927                 req->attributes = OBJ_INHERIT;
2928                 req->share      = FILE_SHARE_READ|FILE_SHARE_WRITE;
2929                 req->fd         = 1;
2930                 wine_server_call(req);
2931                 params->hStdOutput = wine_server_ptr_handle(reply->handle_out);
2932             }
2933             SERVER_END_REQ;
2934         }
2935         if (!params->hStdError)
2936         {
2937             wine_server_send_fd(2);
2938             SERVER_START_REQ( create_console_output )
2939             {
2940                 req->handle_in  = wine_server_obj_handle(conin);
2941                 req->access     = GENERIC_WRITE|GENERIC_READ;
2942                 req->attributes = OBJ_INHERIT;
2943                 req->share      = FILE_SHARE_READ|FILE_SHARE_WRITE;
2944                 req->fd         = 2;
2945                 wine_server_call(req);
2946                 params->hStdError = wine_server_ptr_handle(reply->handle_out);
2947             }
2948             SERVER_END_REQ;
2949         }
2950     }
2951
2952     /* convert value from server:
2953      * + 0 => INVALID_HANDLE_VALUE
2954      * + console handle needs to be mapped
2955      */
2956     if (!params->hStdInput)
2957         params->hStdInput = INVALID_HANDLE_VALUE;
2958     else if (VerifyConsoleIoHandle(console_handle_map(params->hStdInput)))
2959         params->hStdInput = console_handle_map(params->hStdInput);
2960
2961     if (!params->hStdOutput)
2962         params->hStdOutput = INVALID_HANDLE_VALUE;
2963     else if (VerifyConsoleIoHandle(console_handle_map(params->hStdOutput)))
2964         params->hStdOutput = console_handle_map(params->hStdOutput);
2965
2966     if (!params->hStdError)
2967         params->hStdError = INVALID_HANDLE_VALUE;
2968     else if (VerifyConsoleIoHandle(console_handle_map(params->hStdError)))
2969         params->hStdError = console_handle_map(params->hStdError);
2970
2971     return TRUE;
2972 }