Skip tests without error if psapi.dll could not be loaded.
[wine] / dlls / kernel / console.c
1 /*
2  * Win32 kernel 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 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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
42 #include "windef.h"
43 #include "winbase.h"
44 #include "winnls.h"
45 #include "winerror.h"
46 #include "wincon.h"
47 #include "wine/winbase16.h"
48 #include "wine/server.h"
49 #include "wine/exception.h"
50 #include "wine/unicode.h"
51 #include "wine/debug.h"
52 #include "excpt.h"
53 #include "console_private.h"
54 #include "kernel_private.h"
55
56 WINE_DEFAULT_DEBUG_CHANNEL(console);
57
58 static UINT console_input_codepage;
59 static UINT console_output_codepage;
60
61
62 /* map input records to ASCII */
63 static void input_records_WtoA( INPUT_RECORD *buffer, int count )
64 {
65     int i;
66     char ch;
67
68     for (i = 0; i < count; i++)
69     {
70         if (buffer[i].EventType != KEY_EVENT) continue;
71         WideCharToMultiByte( GetConsoleCP(), 0,
72                              &buffer[i].Event.KeyEvent.uChar.UnicodeChar, 1, &ch, 1, NULL, NULL );
73         buffer[i].Event.KeyEvent.uChar.AsciiChar = ch;
74     }
75 }
76
77 /* map input records to Unicode */
78 static void input_records_AtoW( INPUT_RECORD *buffer, int count )
79 {
80     int i;
81     WCHAR ch;
82
83     for (i = 0; i < count; i++)
84     {
85         if (buffer[i].EventType != KEY_EVENT) continue;
86         MultiByteToWideChar( GetConsoleCP(), 0,
87                              &buffer[i].Event.KeyEvent.uChar.AsciiChar, 1, &ch, 1 );
88         buffer[i].Event.KeyEvent.uChar.UnicodeChar = ch;
89     }
90 }
91
92 /* map char infos to ASCII */
93 static void char_info_WtoA( CHAR_INFO *buffer, int count )
94 {
95     char ch;
96
97     while (count-- > 0)
98     {
99         WideCharToMultiByte( GetConsoleOutputCP(), 0, &buffer->Char.UnicodeChar, 1,
100                              &ch, 1, NULL, NULL );
101         buffer->Char.AsciiChar = ch;
102         buffer++;
103     }
104 }
105
106 /* map char infos to Unicode */
107 static void char_info_AtoW( CHAR_INFO *buffer, int count )
108 {
109     WCHAR ch;
110
111     while (count-- > 0)
112     {
113         MultiByteToWideChar( GetConsoleOutputCP(), 0, &buffer->Char.AsciiChar, 1, &ch, 1 );
114         buffer->Char.UnicodeChar = ch;
115         buffer++;
116     }
117 }
118
119
120 /******************************************************************************
121  * GetConsoleWindow [KERNEL32.@]
122  */
123 HWND WINAPI GetConsoleWindow(VOID)
124 {
125     FIXME("stub\n");
126     return NULL;
127 }
128
129
130 /******************************************************************************
131  * GetConsoleCP [KERNEL32.@]  Returns the OEM code page for the console
132  *
133  * RETURNS
134  *    Code page code
135  */
136 UINT WINAPI GetConsoleCP(VOID)
137 {
138     if (!console_input_codepage) 
139     {
140         console_input_codepage = GetOEMCP();
141         TRACE("%u\n", console_input_codepage);
142     }
143     return console_input_codepage;
144 }
145
146
147 /******************************************************************************
148  *  SetConsoleCP         [KERNEL32.@]
149  */
150 BOOL WINAPI SetConsoleCP(UINT cp)
151 {
152     if (!IsValidCodePage( cp )) return FALSE;
153     console_input_codepage = cp;
154     return TRUE;
155 }
156
157
158 /***********************************************************************
159  *            GetConsoleOutputCP   (KERNEL32.@)
160  */
161 UINT WINAPI GetConsoleOutputCP(VOID)
162 {
163     if (!console_output_codepage)
164     {
165         console_output_codepage = GetOEMCP();
166         TRACE("%u\n", console_output_codepage);
167     }
168     return console_output_codepage;
169 }
170
171
172 /******************************************************************************
173  * SetConsoleOutputCP [KERNEL32.@]  Set the output codepage used by the console
174  *
175  * PARAMS
176  *    cp [I] code page to set
177  *
178  * RETURNS
179  *    Success: TRUE
180  *    Failure: FALSE
181  */
182 BOOL WINAPI SetConsoleOutputCP(UINT cp)
183 {
184     if (!IsValidCodePage( cp )) return FALSE;
185     console_output_codepage = cp;
186     return TRUE;
187 }
188
189
190 /***********************************************************************
191  *           Beep   (KERNEL32.@)
192  */
193 BOOL WINAPI Beep( DWORD dwFreq, DWORD dwDur )
194 {
195     static const char beep = '\a';
196     /* dwFreq and dwDur are ignored by Win95 */
197     if (isatty(2)) write( 2, &beep, 1 );
198     return TRUE;
199 }
200
201
202 /******************************************************************
203  *              OpenConsoleW            (KERNEL32.@)
204  *
205  * Undocumented
206  *      Open a handle to the current process console.
207  *      Returns INVALID_HANDLE_VALUE on failure.
208  */
209 HANDLE WINAPI OpenConsoleW(LPCWSTR name, DWORD access, BOOL inherit, DWORD creation)
210 {
211     static const WCHAR coninW[] = {'C','O','N','I','N','$',0};
212     static const WCHAR conoutW[] = {'C','O','N','O','U','T','$',0};
213     BOOL        output;
214     HANDLE ret;
215
216     if (strcmpiW(coninW, name) == 0) 
217         output = FALSE;
218     else if (strcmpiW(conoutW, name) == 0) 
219         output = TRUE;
220     else
221     {
222         SetLastError(ERROR_INVALID_NAME);
223         return INVALID_HANDLE_VALUE;
224     }
225     if (creation != OPEN_EXISTING)
226     {
227         SetLastError(ERROR_INVALID_PARAMETER);
228         return INVALID_HANDLE_VALUE;
229     }
230
231     SERVER_START_REQ( open_console )
232     {
233         req->from    = output;
234         req->access  = access;
235         req->share   = FILE_SHARE_READ | FILE_SHARE_WRITE;
236         req->inherit = inherit;
237         SetLastError(0);
238         wine_server_call_err( req );
239         ret = reply->handle;
240     }
241     SERVER_END_REQ;
242     return ret ? console_handle_map(ret) : INVALID_HANDLE_VALUE;
243 }
244
245 /******************************************************************
246  *              VerifyConsoleIoHandle            (KERNEL32.@)
247  *
248  * Undocumented
249  */
250 BOOL WINAPI VerifyConsoleIoHandle(HANDLE handle)
251 {
252     BOOL ret;
253
254     if (!is_console_handle(handle)) return FALSE;
255     SERVER_START_REQ(get_console_mode)
256     {
257         req->handle = console_handle_unmap(handle);
258         ret = !wine_server_call_err( req );
259     }
260     SERVER_END_REQ;
261     return ret;
262 }
263
264 /******************************************************************
265  *              DuplicateConsoleHandle            (KERNEL32.@)
266  *
267  * Undocumented
268  */
269 HANDLE WINAPI DuplicateConsoleHandle(HANDLE handle, DWORD access, BOOL inherit,
270                                      DWORD options)
271 {
272     HANDLE      ret;
273
274     if (!is_console_handle(handle) ||
275         !DuplicateHandle(GetCurrentProcess(), console_handle_unmap(handle), 
276                          GetCurrentProcess(), &ret, access, inherit, options))
277         return INVALID_HANDLE_VALUE;
278     return console_handle_map(ret);
279 }
280
281 /******************************************************************
282  *              CloseConsoleHandle            (KERNEL32.@)
283  *
284  * Undocumented
285  */
286 BOOL WINAPI CloseConsoleHandle(HANDLE handle)
287 {
288     if (!is_console_handle(handle)) 
289     {
290         SetLastError(ERROR_INVALID_PARAMETER);
291         return FALSE;
292     }
293     return CloseHandle(console_handle_unmap(handle));
294 }
295
296 /******************************************************************
297  *              GetConsoleInputWaitHandle            (KERNEL32.@)
298  *
299  * Undocumented
300  */
301 HANDLE WINAPI GetConsoleInputWaitHandle(void)
302 {
303     static HANDLE console_wait_event;
304  
305     /* FIXME: this is not thread safe */
306     if (!console_wait_event)
307     {
308         SERVER_START_REQ(get_console_wait_event)
309         {
310             if (!wine_server_call_err( req )) console_wait_event = reply->handle;
311         }
312         SERVER_END_REQ;
313     }
314     return console_wait_event;
315 }
316
317
318 /******************************************************************************
319  * WriteConsoleInputA [KERNEL32.@]
320  */
321 BOOL WINAPI WriteConsoleInputA( HANDLE handle, const INPUT_RECORD *buffer,
322                                 DWORD count, LPDWORD written )
323 {
324     INPUT_RECORD *recW;
325     BOOL ret;
326
327     if (!(recW = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*recW) ))) return FALSE;
328     memcpy( recW, buffer, count*sizeof(*recW) );
329     input_records_AtoW( recW, count );
330     ret = WriteConsoleInputW( handle, recW, count, written );
331     HeapFree( GetProcessHeap(), 0, recW );
332     return ret;
333 }
334
335
336 /******************************************************************************
337  * WriteConsoleInputW [KERNEL32.@]
338  */
339 BOOL WINAPI WriteConsoleInputW( HANDLE handle, const INPUT_RECORD *buffer,
340                                 DWORD count, LPDWORD written )
341 {
342     BOOL ret;
343
344     TRACE("(%p,%p,%ld,%p)\n", handle, buffer, count, written);
345
346     if (written) *written = 0;
347     SERVER_START_REQ( write_console_input )
348     {
349         req->handle = console_handle_unmap(handle);
350         wine_server_add_data( req, buffer, count * sizeof(INPUT_RECORD) );
351         if ((ret = !wine_server_call_err( req )) && written)
352             *written = reply->written;
353     }
354     SERVER_END_REQ;
355
356     return ret;
357 }
358
359
360 /***********************************************************************
361  *            WriteConsoleOutputA   (KERNEL32.@)
362  */
363 BOOL WINAPI WriteConsoleOutputA( HANDLE hConsoleOutput, const CHAR_INFO *lpBuffer,
364                                  COORD size, COORD coord, LPSMALL_RECT region )
365 {
366     int y;
367     BOOL ret;
368     COORD new_size, new_coord;
369     CHAR_INFO *ciw;
370
371     new_size.X = min( region->Right - region->Left + 1, size.X - coord.X );
372     new_size.Y = min( region->Bottom - region->Top + 1, size.Y - coord.Y );
373
374     if (new_size.X <= 0 || new_size.Y <= 0)
375     {
376         region->Bottom = region->Top + new_size.Y - 1;
377         region->Right = region->Left + new_size.X - 1;
378         return TRUE;
379     }
380
381     /* only copy the useful rectangle */
382     if (!(ciw = HeapAlloc( GetProcessHeap(), 0, sizeof(CHAR_INFO) * new_size.X * new_size.Y )))
383         return FALSE;
384     for (y = 0; y < new_size.Y; y++)
385     {
386         memcpy( &ciw[y * new_size.X], &lpBuffer[(y + coord.Y) * size.X + coord.X],
387                 new_size.X * sizeof(CHAR_INFO) );
388         char_info_AtoW( ciw, new_size.X );
389     }
390     new_coord.X = new_coord.Y = 0;
391     ret = WriteConsoleOutputW( hConsoleOutput, ciw, new_size, new_coord, region );
392     if (ciw) HeapFree( GetProcessHeap(), 0, ciw );
393     return ret;
394 }
395
396
397 /***********************************************************************
398  *            WriteConsoleOutputW   (KERNEL32.@)
399  */
400 BOOL WINAPI WriteConsoleOutputW( HANDLE hConsoleOutput, const CHAR_INFO *lpBuffer,
401                                  COORD size, COORD coord, LPSMALL_RECT region )
402 {
403     int width, height, y;
404     BOOL ret = TRUE;
405
406     TRACE("(%p,%p,(%d,%d),(%d,%d),(%d,%dx%d,%d)\n",
407           hConsoleOutput, lpBuffer, size.X, size.Y, coord.X, coord.Y,
408           region->Left, region->Top, region->Right, region->Bottom);
409
410     width = min( region->Right - region->Left + 1, size.X - coord.X );
411     height = min( region->Bottom - region->Top + 1, size.Y - coord.Y );
412
413     if (width > 0 && height > 0)
414     {
415         for (y = 0; y < height; y++)
416         {
417             SERVER_START_REQ( write_console_output )
418             {
419                 req->handle = console_handle_unmap(hConsoleOutput);
420                 req->x      = region->Left;
421                 req->y      = region->Top + y;
422                 req->mode   = CHAR_INFO_MODE_TEXTATTR;
423                 req->wrap   = FALSE;
424                 wine_server_add_data( req, &lpBuffer[(y + coord.Y) * size.X + coord.X],
425                                       width * sizeof(CHAR_INFO));
426                 if ((ret = !wine_server_call_err( req )))
427                 {
428                     width  = min( width, reply->width - region->Left );
429                     height = min( height, reply->height - region->Top );
430                 }
431             }
432             SERVER_END_REQ;
433             if (!ret) break;
434         }
435     }
436     region->Bottom = region->Top + height - 1;
437     region->Right = region->Left + width - 1;
438     return ret;
439 }
440
441
442 /******************************************************************************
443  * WriteConsoleOutputCharacterA [KERNEL32.@]  Copies character to consecutive
444  *                                            cells in the console screen buffer
445  *
446  * PARAMS
447  *    hConsoleOutput    [I] Handle to screen buffer
448  *    str               [I] Pointer to buffer with chars to write
449  *    length            [I] Number of cells to write to
450  *    coord             [I] Coords of first cell
451  *    lpNumCharsWritten [O] Pointer to number of cells written
452  */
453 BOOL WINAPI WriteConsoleOutputCharacterA( HANDLE hConsoleOutput, LPCSTR str, DWORD length,
454                                           COORD coord, LPDWORD lpNumCharsWritten )
455 {
456     BOOL ret;
457     LPWSTR strW;
458     DWORD lenW;
459
460     TRACE("(%p,%s,%ld,%dx%d,%p)\n", hConsoleOutput,
461           debugstr_an(str, length), length, coord.X, coord.Y, lpNumCharsWritten);
462
463     lenW = MultiByteToWideChar( GetConsoleOutputCP(), 0, str, length, NULL, 0 );
464
465     if (lpNumCharsWritten) *lpNumCharsWritten = 0;
466
467     if (!(strW = HeapAlloc( GetProcessHeap(), 0, lenW * sizeof(WCHAR) ))) return FALSE;
468     MultiByteToWideChar( GetConsoleOutputCP(), 0, str, length, strW, lenW );
469
470     ret = WriteConsoleOutputCharacterW( hConsoleOutput, strW, lenW, coord, lpNumCharsWritten );
471     HeapFree( GetProcessHeap(), 0, strW );
472     return ret;
473 }
474
475
476 /******************************************************************************
477  * WriteConsoleOutputAttribute [KERNEL32.@]  Sets attributes for some cells in
478  *                                           the console screen buffer
479  *
480  * PARAMS
481  *    hConsoleOutput    [I] Handle to screen buffer
482  *    attr              [I] Pointer to buffer with write attributes
483  *    length            [I] Number of cells to write to
484  *    coord             [I] Coords of first cell
485  *    lpNumAttrsWritten [O] Pointer to number of cells written
486  *
487  * RETURNS
488  *    Success: TRUE
489  *    Failure: FALSE
490  *
491  */
492 BOOL WINAPI WriteConsoleOutputAttribute( HANDLE hConsoleOutput, CONST WORD *attr, DWORD length,
493                                          COORD coord, LPDWORD lpNumAttrsWritten )
494 {
495     BOOL ret;
496
497     TRACE("(%p,%p,%ld,%dx%d,%p)\n", hConsoleOutput,attr,length,coord.X,coord.Y,lpNumAttrsWritten);
498
499     SERVER_START_REQ( write_console_output )
500     {
501         req->handle = console_handle_unmap(hConsoleOutput);
502         req->x      = coord.X;
503         req->y      = coord.Y;
504         req->mode   = CHAR_INFO_MODE_ATTR;
505         req->wrap   = TRUE;
506         wine_server_add_data( req, attr, length * sizeof(WORD) );
507         if ((ret = !wine_server_call_err( req )))
508         {
509             if (lpNumAttrsWritten) *lpNumAttrsWritten = reply->written;
510         }
511     }
512     SERVER_END_REQ;
513     return ret;
514 }
515
516
517 /******************************************************************************
518  * FillConsoleOutputCharacterA [KERNEL32.@]
519  *
520  * PARAMS
521  *    hConsoleOutput    [I] Handle to screen buffer
522  *    ch                [I] Character to write
523  *    length            [I] Number of cells to write to
524  *    coord             [I] Coords of first cell
525  *    lpNumCharsWritten [O] Pointer to number of cells written
526  *
527  * RETURNS
528  *    Success: TRUE
529  *    Failure: FALSE
530  */
531 BOOL WINAPI FillConsoleOutputCharacterA( HANDLE hConsoleOutput, CHAR ch, DWORD length,
532                                          COORD coord, LPDWORD lpNumCharsWritten )
533 {
534     WCHAR wch;
535
536     MultiByteToWideChar( GetConsoleOutputCP(), 0, &ch, 1, &wch, 1 );
537     return FillConsoleOutputCharacterW(hConsoleOutput, wch, length, coord, lpNumCharsWritten);
538 }
539
540
541 /******************************************************************************
542  * FillConsoleOutputCharacterW [KERNEL32.@]  Writes characters to console
543  *
544  * PARAMS
545  *    hConsoleOutput    [I] Handle to screen buffer
546  *    ch                [I] Character to write
547  *    length            [I] Number of cells to write to
548  *    coord             [I] Coords of first cell
549  *    lpNumCharsWritten [O] Pointer to number of cells written
550  *
551  * RETURNS
552  *    Success: TRUE
553  *    Failure: FALSE
554  */
555 BOOL WINAPI FillConsoleOutputCharacterW( HANDLE hConsoleOutput, WCHAR ch, DWORD length,
556                                          COORD coord, LPDWORD lpNumCharsWritten)
557 {
558     BOOL ret;
559
560     TRACE("(%p,%s,%ld,(%dx%d),%p)\n",
561           hConsoleOutput, debugstr_wn(&ch, 1), length, coord.X, coord.Y, lpNumCharsWritten);
562
563     SERVER_START_REQ( fill_console_output )
564     {
565         req->handle  = console_handle_unmap(hConsoleOutput);
566         req->x       = coord.X;
567         req->y       = coord.Y;
568         req->mode    = CHAR_INFO_MODE_TEXT;
569         req->wrap    = TRUE;
570         req->data.ch = ch;
571         req->count   = length;
572         if ((ret = !wine_server_call_err( req )))
573         {
574             if (lpNumCharsWritten) *lpNumCharsWritten = reply->written;
575         }
576     }
577     SERVER_END_REQ;
578     return ret;
579 }
580
581
582 /******************************************************************************
583  * FillConsoleOutputAttribute [KERNEL32.@]  Sets attributes for console
584  *
585  * PARAMS
586  *    hConsoleOutput    [I] Handle to screen buffer
587  *    attr              [I] Color attribute to write
588  *    length            [I] Number of cells to write to
589  *    coord             [I] Coords of first cell
590  *    lpNumAttrsWritten [O] Pointer to number of cells written
591  *
592  * RETURNS
593  *    Success: TRUE
594  *    Failure: FALSE
595  */
596 BOOL WINAPI FillConsoleOutputAttribute( HANDLE hConsoleOutput, WORD attr, DWORD length,
597                                         COORD coord, LPDWORD lpNumAttrsWritten )
598 {
599     BOOL ret;
600
601     TRACE("(%p,%d,%ld,(%dx%d),%p)\n",
602           hConsoleOutput, attr, length, coord.X, coord.Y, lpNumAttrsWritten);
603
604     SERVER_START_REQ( fill_console_output )
605     {
606         req->handle    = console_handle_unmap(hConsoleOutput);
607         req->x         = coord.X;
608         req->y         = coord.Y;
609         req->mode      = CHAR_INFO_MODE_ATTR;
610         req->wrap      = TRUE;
611         req->data.attr = attr;
612         req->count     = length;
613         if ((ret = !wine_server_call_err( req )))
614         {
615             if (lpNumAttrsWritten) *lpNumAttrsWritten = reply->written;
616         }
617     }
618     SERVER_END_REQ;
619     return ret;
620 }
621
622
623 /******************************************************************************
624  * ReadConsoleOutputCharacterA [KERNEL32.@]
625  *
626  */
627 BOOL WINAPI ReadConsoleOutputCharacterA(HANDLE hConsoleOutput, LPSTR lpstr, DWORD count,
628                                         COORD coord, LPDWORD read_count)
629 {
630     DWORD read;
631     BOOL ret;
632     LPWSTR wptr = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR));
633
634     if (read_count) *read_count = 0;
635     if (!wptr) return FALSE;
636
637     if ((ret = ReadConsoleOutputCharacterW( hConsoleOutput, wptr, count, coord, &read )))
638     {
639         read = WideCharToMultiByte( GetConsoleOutputCP(), 0, wptr, read, lpstr, count, NULL, NULL);
640         if (read_count) *read_count = read;
641     }
642     HeapFree( GetProcessHeap(), 0, wptr );
643     return ret;
644 }
645
646
647 /******************************************************************************
648  * ReadConsoleOutputCharacterW [KERNEL32.@]
649  *
650  */
651 BOOL WINAPI ReadConsoleOutputCharacterW( HANDLE hConsoleOutput, LPWSTR buffer, DWORD count,
652                                          COORD coord, LPDWORD read_count )
653 {
654     BOOL ret;
655
656     TRACE( "(%p,%p,%ld,%dx%d,%p)\n", hConsoleOutput, buffer, count, coord.X, coord.Y, read_count );
657
658     SERVER_START_REQ( read_console_output )
659     {
660         req->handle = console_handle_unmap(hConsoleOutput);
661         req->x      = coord.X;
662         req->y      = coord.Y;
663         req->mode   = CHAR_INFO_MODE_TEXT;
664         req->wrap   = TRUE;
665         wine_server_set_reply( req, buffer, count * sizeof(WCHAR) );
666         if ((ret = !wine_server_call_err( req )))
667         {
668             if (read_count) *read_count = wine_server_reply_size(reply) / sizeof(WCHAR);
669         }
670     }
671     SERVER_END_REQ;
672     return ret;
673 }
674
675
676 /******************************************************************************
677  *  ReadConsoleOutputAttribute [KERNEL32.@]
678  */
679 BOOL WINAPI ReadConsoleOutputAttribute(HANDLE hConsoleOutput, LPWORD lpAttribute, DWORD length,
680                                        COORD coord, LPDWORD read_count)
681 {
682     BOOL ret;
683
684     TRACE("(%p,%p,%ld,%dx%d,%p)\n",
685           hConsoleOutput, lpAttribute, length, coord.X, coord.Y, read_count);
686
687     SERVER_START_REQ( read_console_output )
688     {
689         req->handle = console_handle_unmap(hConsoleOutput);
690         req->x      = coord.X;
691         req->y      = coord.Y;
692         req->mode   = CHAR_INFO_MODE_ATTR;
693         req->wrap   = TRUE;
694         wine_server_set_reply( req, lpAttribute, length * sizeof(WORD) );
695         if ((ret = !wine_server_call_err( req )))
696         {
697             if (read_count) *read_count = wine_server_reply_size(reply) / sizeof(WORD);
698         }
699     }
700     SERVER_END_REQ;
701     return ret;
702 }
703
704
705 /******************************************************************************
706  *  ReadConsoleOutputA [KERNEL32.@]
707  *
708  */
709 BOOL WINAPI ReadConsoleOutputA( HANDLE hConsoleOutput, LPCHAR_INFO lpBuffer, COORD size,
710                                 COORD coord, LPSMALL_RECT region )
711 {
712     BOOL ret;
713     int y;
714
715     ret = ReadConsoleOutputW( hConsoleOutput, lpBuffer, size, coord, region );
716     if (ret && region->Right >= region->Left)
717     {
718         for (y = 0; y <= region->Bottom - region->Top; y++)
719         {
720             char_info_WtoA( &lpBuffer[(coord.Y + y) * size.X + coord.X],
721                             region->Right - region->Left + 1 );
722         }
723     }
724     return ret;
725 }
726
727
728 /******************************************************************************
729  *  ReadConsoleOutputW [KERNEL32.@]
730  *
731  * NOTE: The NT4 (sp5) kernel crashes on me if size is (0,0). I don't
732  * think we need to be *that* compatible.  -- AJ
733  */
734 BOOL WINAPI ReadConsoleOutputW( HANDLE hConsoleOutput, LPCHAR_INFO lpBuffer, COORD size,
735                                 COORD coord, LPSMALL_RECT region )
736 {
737     int width, height, y;
738     BOOL ret = TRUE;
739
740     width = min( region->Right - region->Left + 1, size.X - coord.X );
741     height = min( region->Bottom - region->Top + 1, size.Y - coord.Y );
742
743     if (width > 0 && height > 0)
744     {
745         for (y = 0; y < height; y++)
746         {
747             SERVER_START_REQ( read_console_output )
748             {
749                 req->handle = console_handle_unmap(hConsoleOutput);
750                 req->x      = region->Left;
751                 req->y      = region->Top + y;
752                 req->mode   = CHAR_INFO_MODE_TEXTATTR;
753                 req->wrap   = FALSE;
754                 wine_server_set_reply( req, &lpBuffer[(y+coord.Y) * size.X + coord.X],
755                                        width * sizeof(CHAR_INFO) );
756                 if ((ret = !wine_server_call_err( req )))
757                 {
758                     width  = min( width, reply->width - region->Left );
759                     height = min( height, reply->height - region->Top );
760                 }
761             }
762             SERVER_END_REQ;
763             if (!ret) break;
764         }
765     }
766     region->Bottom = region->Top + height - 1;
767     region->Right = region->Left + width - 1;
768     return ret;
769 }
770
771
772 /******************************************************************************
773  * ReadConsoleInputA [KERNEL32.@]  Reads data from a console
774  *
775  * PARAMS
776  *    handle   [I] Handle to console input buffer
777  *    buffer   [O] Address of buffer for read data
778  *    count    [I] Number of records to read
779  *    pRead    [O] Address of number of records read
780  *
781  * RETURNS
782  *    Success: TRUE
783  *    Failure: FALSE
784  */
785 BOOL WINAPI ReadConsoleInputA( HANDLE handle, PINPUT_RECORD buffer, DWORD count, LPDWORD pRead )
786 {
787     DWORD read;
788
789     if (!ReadConsoleInputW( handle, buffer, count, &read )) return FALSE;
790     input_records_WtoA( buffer, read );
791     if (pRead) *pRead = read;
792     return TRUE;
793 }
794
795
796 /***********************************************************************
797  *            PeekConsoleInputA   (KERNEL32.@)
798  *
799  * Gets 'count' first events (or less) from input queue.
800  */
801 BOOL WINAPI PeekConsoleInputA( HANDLE handle, PINPUT_RECORD buffer, DWORD count, LPDWORD pRead )
802 {
803     DWORD read;
804
805     if (!PeekConsoleInputW( handle, buffer, count, &read )) return FALSE;
806     input_records_WtoA( buffer, read );
807     if (pRead) *pRead = read;
808     return TRUE;
809 }
810
811
812 /***********************************************************************
813  *            PeekConsoleInputW   (KERNEL32.@)
814  */
815 BOOL WINAPI PeekConsoleInputW( HANDLE handle, PINPUT_RECORD buffer, DWORD count, LPDWORD read )
816 {
817     BOOL ret;
818     SERVER_START_REQ( read_console_input )
819     {
820         req->handle = console_handle_unmap(handle);
821         req->flush  = FALSE;
822         wine_server_set_reply( req, buffer, count * sizeof(INPUT_RECORD) );
823         if ((ret = !wine_server_call_err( req )))
824         {
825             if (read) *read = count ? reply->read : 0;
826         }
827     }
828     SERVER_END_REQ;
829     return ret;
830 }
831
832
833 /***********************************************************************
834  *            GetNumberOfConsoleInputEvents   (KERNEL32.@)
835  */
836 BOOL WINAPI GetNumberOfConsoleInputEvents( HANDLE handle, LPDWORD nrofevents )
837 {
838     BOOL ret;
839     SERVER_START_REQ( read_console_input )
840     {
841         req->handle = console_handle_unmap(handle);
842         req->flush  = FALSE;
843         if ((ret = !wine_server_call_err( req )))
844         {
845             if (nrofevents) *nrofevents = reply->read;
846         }
847     }
848     SERVER_END_REQ;
849     return ret;
850 }
851
852
853 /******************************************************************************
854  * read_console_input
855  *
856  * Helper function for ReadConsole, ReadConsoleInput and FlushConsoleInputBuffer
857  *
858  * Returns 
859  *      0 for error, 1 for no INPUT_RECORD ready, 2 with INPUT_RECORD ready
860  */
861 enum read_console_input_return {rci_error = 0, rci_timeout = 1, rci_gotone = 2};
862 static enum read_console_input_return read_console_input(HANDLE handle, PINPUT_RECORD ir, DWORD timeout)
863 {
864     enum read_console_input_return      ret;
865
866     if (WaitForSingleObject(GetConsoleInputWaitHandle(), timeout) != WAIT_OBJECT_0)
867         return rci_timeout;
868     SERVER_START_REQ( read_console_input )
869     {
870         req->handle = console_handle_unmap(handle);
871         req->flush = TRUE;
872         wine_server_set_reply( req, ir, sizeof(INPUT_RECORD) );
873         if (wine_server_call_err( req ) || !reply->read) ret = rci_error;
874         else ret = rci_gotone;
875     }
876     SERVER_END_REQ;
877
878     return ret;
879 }
880
881
882 /***********************************************************************
883  *            FlushConsoleInputBuffer   (KERNEL32.@)
884  */
885 BOOL WINAPI FlushConsoleInputBuffer( HANDLE handle )
886 {
887     enum read_console_input_return      last;
888     INPUT_RECORD                        ir;
889
890     while ((last = read_console_input(handle, &ir, 0)) == rci_gotone);
891
892     return last == rci_timeout;
893 }
894
895
896 /***********************************************************************
897  *            SetConsoleTitleA   (KERNEL32.@)
898  */
899 BOOL WINAPI SetConsoleTitleA( LPCSTR title )
900 {
901     LPWSTR titleW;
902     BOOL ret;
903
904     DWORD len = MultiByteToWideChar( GetConsoleOutputCP(), 0, title, -1, NULL, 0 );
905     if (!(titleW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)))) return FALSE;
906     MultiByteToWideChar( GetConsoleOutputCP(), 0, title, -1, titleW, len );
907     ret = SetConsoleTitleW(titleW);
908     HeapFree(GetProcessHeap(), 0, titleW);
909     return ret;
910 }
911
912
913 /***********************************************************************
914  *            GetConsoleTitleA   (KERNEL32.@)
915  */
916 DWORD WINAPI GetConsoleTitleA(LPSTR title, DWORD size)
917 {
918     WCHAR *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * size);
919     DWORD ret;
920
921     if (!ptr) return 0;
922     ret = GetConsoleTitleW( ptr, size );
923     if (ret)
924     {
925         WideCharToMultiByte( GetConsoleOutputCP(), 0, ptr, ret + 1, title, size, NULL, NULL);
926         ret = strlen(title);
927     }
928     HeapFree(GetProcessHeap(), 0, ptr);
929     return ret;
930 }
931
932
933 /******************************************************************************
934  * GetConsoleTitleW [KERNEL32.@]  Retrieves title string for console
935  *
936  * PARAMS
937  *    title [O] Address of buffer for title
938  *    size  [I] Size of buffer
939  *
940  * RETURNS
941  *    Success: Length of string copied
942  *    Failure: 0
943  */
944 DWORD WINAPI GetConsoleTitleW(LPWSTR title, DWORD size)
945 {
946     DWORD ret = 0;
947
948     SERVER_START_REQ( get_console_input_info )
949     {
950         req->handle = 0;
951         wine_server_set_reply( req, title, (size-1) * sizeof(WCHAR) );
952         if (!wine_server_call_err( req ))
953         {
954             ret = wine_server_reply_size(reply) / sizeof(WCHAR);
955             title[ret] = 0;
956         }
957     }
958     SERVER_END_REQ;
959     return ret;
960 }
961
962
963 /***********************************************************************
964  *            GetLargestConsoleWindowSize   (KERNEL32.@)
965  *
966  * NOTE
967  *      This should return a COORD, but calling convention for returning
968  *      structures is different between Windows and gcc on i386.
969  *
970  * VERSION: [i386]
971  */
972 #ifdef __i386__
973 #undef GetLargestConsoleWindowSize
974 DWORD WINAPI GetLargestConsoleWindowSize(HANDLE hConsoleOutput)
975 {
976     union {
977         COORD c;
978         DWORD w;
979     } x;
980     x.c.X = 80;
981     x.c.Y = 24;
982     TRACE("(%p), returning %dx%d (%lx)\n", hConsoleOutput, x.c.X, x.c.Y, x.w);
983     return x.w;
984 }
985 #endif /* defined(__i386__) */
986
987
988 /***********************************************************************
989  *            GetLargestConsoleWindowSize   (KERNEL32.@)
990  *
991  * NOTE
992  *      This should return a COORD, but calling convention for returning
993  *      structures is different between Windows and gcc on i386.
994  *
995  * VERSION: [!i386]
996  */
997 #ifndef __i386__
998 COORD WINAPI GetLargestConsoleWindowSize(HANDLE hConsoleOutput)
999 {
1000     COORD c;
1001     c.X = 80;
1002     c.Y = 24;
1003     TRACE("(%p), returning %dx%d\n", hConsoleOutput, c.X, c.Y);
1004     return c;
1005 }
1006 #endif /* defined(__i386__) */
1007
1008 static WCHAR*   S_EditString /* = NULL */;
1009 static unsigned S_EditStrPos /* = 0 */;
1010
1011 /***********************************************************************
1012  *            FreeConsole (KERNEL32.@)
1013  */
1014 BOOL WINAPI FreeConsole(VOID)
1015 {
1016     BOOL ret;
1017
1018     SERVER_START_REQ(free_console)
1019     {
1020         ret = !wine_server_call_err( req );
1021     }
1022     SERVER_END_REQ;
1023     return ret;
1024 }
1025
1026 /******************************************************************
1027  *              start_console_renderer
1028  *
1029  * helper for AllocConsole
1030  * starts the renderer process
1031  */
1032 static  BOOL    start_console_renderer_helper(const char* appname, STARTUPINFOA* si,
1033                                               HANDLE hEvent)
1034 {
1035     char                buffer[1024];
1036     int                 ret;
1037     PROCESS_INFORMATION pi;
1038
1039     /* FIXME: use dynamic allocation for most of the buffers below */
1040     ret = snprintf(buffer, sizeof(buffer), "%s --use-event=%d", appname, (INT)hEvent);
1041     if ((ret > -1) && (ret < sizeof(buffer)) &&
1042         CreateProcessA(NULL, buffer, NULL, NULL, TRUE, DETACHED_PROCESS,
1043                        NULL, NULL, si, &pi))
1044     {
1045         if (WaitForSingleObject(hEvent, INFINITE) != WAIT_OBJECT_0) return FALSE;
1046
1047         TRACE("Started wineconsole pid=%08lx tid=%08lx\n",
1048               pi.dwProcessId, pi.dwThreadId);
1049
1050         return TRUE;
1051     }
1052     return FALSE;
1053 }
1054
1055 static  BOOL    start_console_renderer(STARTUPINFOA* si)
1056 {
1057     HANDLE              hEvent = 0;
1058     LPSTR               p;
1059     OBJECT_ATTRIBUTES   attr;
1060     BOOL                ret = FALSE;
1061
1062     attr.Length                   = sizeof(attr);
1063     attr.RootDirectory            = 0;
1064     attr.Attributes               = OBJ_INHERIT;
1065     attr.ObjectName               = NULL;
1066     attr.SecurityDescriptor       = NULL;
1067     attr.SecurityQualityOfService = NULL;
1068
1069     NtCreateEvent(&hEvent, EVENT_ALL_ACCESS, &attr, TRUE, FALSE);
1070     if (!hEvent) return FALSE;
1071
1072     /* first try environment variable */
1073     if ((p = getenv("WINECONSOLE")) != NULL)
1074     {
1075         ret = start_console_renderer_helper(p, si, hEvent);
1076         if (!ret)
1077             ERR("Couldn't launch Wine console from WINECONSOLE env var (%s)... "
1078                 "trying default access\n", p);
1079     }
1080
1081     /* then try the regular PATH */
1082     if (!ret)
1083         ret = start_console_renderer_helper("wineconsole", si, hEvent);
1084
1085     CloseHandle(hEvent);
1086     return ret;
1087 }
1088
1089 /***********************************************************************
1090  *            AllocConsole (KERNEL32.@)
1091  *
1092  * creates an xterm with a pty to our program
1093  */
1094 BOOL WINAPI AllocConsole(void)
1095 {
1096     HANDLE              handle_in = INVALID_HANDLE_VALUE;
1097     HANDLE              handle_out = INVALID_HANDLE_VALUE;
1098     HANDLE              handle_err = INVALID_HANDLE_VALUE;
1099     STARTUPINFOA        siCurrent;
1100     STARTUPINFOA        siConsole;
1101     char                buffer[1024];
1102     SECURITY_ATTRIBUTES sa;
1103
1104     TRACE("()\n");
1105
1106     handle_in = CreateFileA( "CONIN$", GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,
1107                              0, NULL, OPEN_EXISTING, 0, 0 );
1108
1109     if (handle_in != INVALID_HANDLE_VALUE)
1110     {
1111         /* we already have a console opened on this process, don't create a new one */
1112         CloseHandle(handle_in);
1113         return FALSE;
1114     }
1115
1116     GetStartupInfoA(&siCurrent);
1117
1118     memset(&siConsole, 0, sizeof(siConsole));
1119     siConsole.cb = sizeof(siConsole);
1120     /* setup a view arguments for wineconsole (it'll use them as default values)  */
1121     if (siCurrent.dwFlags & STARTF_USECOUNTCHARS)
1122     {
1123         siConsole.dwFlags |= STARTF_USECOUNTCHARS;
1124         siConsole.dwXCountChars = siCurrent.dwXCountChars;
1125         siConsole.dwYCountChars = siCurrent.dwYCountChars;
1126     }
1127     if (siCurrent.dwFlags & STARTF_USEFILLATTRIBUTE)
1128     {
1129         siConsole.dwFlags |= STARTF_USEFILLATTRIBUTE;
1130         siConsole.dwFillAttribute = siCurrent.dwFillAttribute;
1131     }
1132     /* FIXME (should pass the unicode form) */
1133     if (siCurrent.lpTitle)
1134         siConsole.lpTitle = siCurrent.lpTitle;
1135     else if (GetModuleFileNameA(0, buffer, sizeof(buffer)))
1136     {
1137         buffer[sizeof(buffer) - 1] = '\0';
1138         siConsole.lpTitle = buffer;
1139     }
1140
1141     if (!start_console_renderer(&siConsole))
1142         goto the_end;
1143
1144     /* all std I/O handles are inheritable by default */
1145     sa.nLength = sizeof(sa);
1146     sa.lpSecurityDescriptor = NULL;
1147     sa.bInheritHandle = TRUE;
1148
1149     handle_in = CreateFileA( "CONIN$", GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,
1150                              0, &sa, OPEN_EXISTING, 0, 0 );
1151     if (handle_in == INVALID_HANDLE_VALUE) goto the_end;
1152
1153     handle_out = CreateFileA( "CONOUT$", GENERIC_READ|GENERIC_WRITE,
1154                               0, &sa, OPEN_EXISTING, 0, 0 );
1155     if (handle_out == INVALID_HANDLE_VALUE) goto the_end;
1156
1157     if (!DuplicateHandle(GetCurrentProcess(), handle_out, GetCurrentProcess(), &handle_err,
1158                          0, TRUE, DUPLICATE_SAME_ACCESS))
1159         goto the_end;
1160
1161     /* NT resets the STD_*_HANDLEs on console alloc */
1162     SetStdHandle(STD_INPUT_HANDLE,  handle_in);
1163     SetStdHandle(STD_OUTPUT_HANDLE, handle_out);
1164     SetStdHandle(STD_ERROR_HANDLE,  handle_err);
1165
1166     SetLastError(ERROR_SUCCESS);
1167
1168     return TRUE;
1169
1170  the_end:
1171     ERR("Can't allocate console\n");
1172     if (handle_in != INVALID_HANDLE_VALUE)      CloseHandle(handle_in);
1173     if (handle_out != INVALID_HANDLE_VALUE)     CloseHandle(handle_out);
1174     if (handle_err != INVALID_HANDLE_VALUE)     CloseHandle(handle_err);
1175     FreeConsole();
1176     return FALSE;
1177 }
1178
1179
1180 /***********************************************************************
1181  *            ReadConsoleA   (KERNEL32.@)
1182  */
1183 BOOL WINAPI ReadConsoleA(HANDLE hConsoleInput, LPVOID lpBuffer, DWORD nNumberOfCharsToRead,
1184                          LPDWORD lpNumberOfCharsRead, LPVOID lpReserved)
1185 {
1186     LPWSTR      ptr = HeapAlloc(GetProcessHeap(), 0, nNumberOfCharsToRead * sizeof(WCHAR));
1187     DWORD       ncr = 0;
1188     BOOL        ret;
1189
1190     if ((ret = ReadConsoleW(hConsoleInput, ptr, nNumberOfCharsToRead, &ncr, NULL)))
1191         ncr = WideCharToMultiByte(CP_ACP, 0, ptr, ncr, lpBuffer, nNumberOfCharsToRead, NULL, NULL);
1192
1193     if (lpNumberOfCharsRead) *lpNumberOfCharsRead = ncr;
1194     HeapFree(GetProcessHeap(), 0, ptr);
1195
1196     return ret;
1197 }
1198
1199 /***********************************************************************
1200  *            ReadConsoleW   (KERNEL32.@)
1201  */
1202 BOOL WINAPI ReadConsoleW(HANDLE hConsoleInput, LPVOID lpBuffer,
1203                          DWORD nNumberOfCharsToRead, LPDWORD lpNumberOfCharsRead, LPVOID lpReserved)
1204 {
1205     DWORD       charsread;
1206     LPWSTR      xbuf = (LPWSTR)lpBuffer;
1207     DWORD       mode;
1208
1209     TRACE("(%p,%p,%ld,%p,%p)\n",
1210           hConsoleInput, lpBuffer, nNumberOfCharsToRead, lpNumberOfCharsRead, lpReserved);
1211
1212     if (!GetConsoleMode(hConsoleInput, &mode))
1213         return FALSE;
1214
1215     if (mode & ENABLE_LINE_INPUT)
1216     {
1217         if (!S_EditString || S_EditString[S_EditStrPos] == 0)
1218         {
1219             if (S_EditString) HeapFree(GetProcessHeap(), 0, S_EditString);
1220             if (!(S_EditString = CONSOLE_Readline(hConsoleInput)))
1221                 return FALSE;
1222             S_EditStrPos = 0;
1223         }
1224         charsread = lstrlenW(&S_EditString[S_EditStrPos]);
1225         if (charsread > nNumberOfCharsToRead) charsread = nNumberOfCharsToRead;
1226         memcpy(xbuf, &S_EditString[S_EditStrPos], charsread * sizeof(WCHAR));
1227         S_EditStrPos += charsread;
1228     }
1229     else
1230     {
1231         INPUT_RECORD    ir;
1232         DWORD           timeout = INFINITE;
1233
1234         /* FIXME: should we read at least 1 char? The SDK does not say */
1235         /* wait for at least one available input record (it doesn't mean we'll have
1236          * chars stored in xbuf...)
1237          */
1238         charsread = 0;
1239         do 
1240         {
1241             if (read_console_input(hConsoleInput, &ir, timeout) != rci_gotone) break;
1242             timeout = 0;
1243             if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown &&
1244                 ir.Event.KeyEvent.uChar.UnicodeChar &&
1245                 !(ir.Event.KeyEvent.dwControlKeyState & ENHANCED_KEY))
1246             {
1247                 xbuf[charsread++] = ir.Event.KeyEvent.uChar.UnicodeChar;
1248             }
1249         } while (charsread < nNumberOfCharsToRead);
1250         /* nothing has been read */
1251         if (timeout == INFINITE) return FALSE;
1252     }
1253
1254     if (lpNumberOfCharsRead) *lpNumberOfCharsRead = charsread;
1255
1256     return TRUE;
1257 }
1258
1259
1260 /***********************************************************************
1261  *            ReadConsoleInputW   (KERNEL32.@)
1262  */
1263 BOOL WINAPI ReadConsoleInputW(HANDLE hConsoleInput, PINPUT_RECORD lpBuffer,
1264                               DWORD nLength, LPDWORD lpNumberOfEventsRead)
1265 {
1266     DWORD idx = 0;
1267     DWORD timeout = INFINITE;
1268
1269     if (!nLength)
1270     {
1271         if (lpNumberOfEventsRead) *lpNumberOfEventsRead = 0;
1272         return TRUE;
1273     }
1274
1275     /* loop until we get at least one event */
1276     while (read_console_input(hConsoleInput, &lpBuffer[idx], timeout) == rci_gotone &&
1277            ++idx < nLength)
1278         timeout = 0;
1279
1280     if (lpNumberOfEventsRead) *lpNumberOfEventsRead = idx;
1281     return idx != 0;
1282 }
1283
1284
1285 /******************************************************************************
1286  * WriteConsoleOutputCharacterW [KERNEL32.@]  Copies character to consecutive
1287  *                                            cells in the console screen buffer
1288  *
1289  * PARAMS
1290  *    hConsoleOutput    [I] Handle to screen buffer
1291  *    str               [I] Pointer to buffer with chars to write
1292  *    length            [I] Number of cells to write to
1293  *    coord             [I] Coords of first cell
1294  *    lpNumCharsWritten [O] Pointer to number of cells written
1295  *
1296  * RETURNS
1297  *    Success: TRUE
1298  *    Failure: FALSE
1299  *
1300  */
1301 BOOL WINAPI WriteConsoleOutputCharacterW( HANDLE hConsoleOutput, LPCWSTR str, DWORD length,
1302                                           COORD coord, LPDWORD lpNumCharsWritten )
1303 {
1304     BOOL ret;
1305
1306     TRACE("(%p,%s,%ld,%dx%d,%p)\n", hConsoleOutput,
1307           debugstr_wn(str, length), length, coord.X, coord.Y, lpNumCharsWritten);
1308
1309     SERVER_START_REQ( write_console_output )
1310     {
1311         req->handle = console_handle_unmap(hConsoleOutput);
1312         req->x      = coord.X;
1313         req->y      = coord.Y;
1314         req->mode   = CHAR_INFO_MODE_TEXT;
1315         req->wrap   = TRUE;
1316         wine_server_add_data( req, str, length * sizeof(WCHAR) );
1317         if ((ret = !wine_server_call_err( req )))
1318         {
1319             if (lpNumCharsWritten) *lpNumCharsWritten = reply->written;
1320         }
1321     }
1322     SERVER_END_REQ;
1323     return ret;
1324 }
1325
1326
1327 /******************************************************************************
1328  * SetConsoleTitleW [KERNEL32.@]  Sets title bar string for console
1329  *
1330  * PARAMS
1331  *    title [I] Address of new title
1332  *
1333  * RETURNS
1334  *    Success: TRUE
1335  *    Failure: FALSE
1336  */
1337 BOOL WINAPI SetConsoleTitleW(LPCWSTR title)
1338 {
1339     BOOL ret;
1340
1341     TRACE("(%s)\n", debugstr_w(title));
1342     SERVER_START_REQ( set_console_input_info )
1343     {
1344         req->handle = 0;
1345         req->mask = SET_CONSOLE_INPUT_INFO_TITLE;
1346         wine_server_add_data( req, title, strlenW(title) * sizeof(WCHAR) );
1347         ret = !wine_server_call_err( req );
1348     }
1349     SERVER_END_REQ;
1350     return ret;
1351 }
1352
1353
1354 /***********************************************************************
1355  *            GetNumberOfConsoleMouseButtons   (KERNEL32.@)
1356  */
1357 BOOL WINAPI GetNumberOfConsoleMouseButtons(LPDWORD nrofbuttons)
1358 {
1359     FIXME("(%p): stub\n", nrofbuttons);
1360     *nrofbuttons = 2;
1361     return TRUE;
1362 }
1363
1364 /******************************************************************************
1365  *  SetConsoleInputExeNameW      [KERNEL32.@]
1366  *
1367  * BUGS
1368  *   Unimplemented
1369  */
1370 BOOL WINAPI SetConsoleInputExeNameW(LPCWSTR name)
1371 {
1372     FIXME("(%s): stub!\n", debugstr_w(name));
1373
1374     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1375     return TRUE;
1376 }
1377
1378 /******************************************************************************
1379  *  SetConsoleInputExeNameA      [KERNEL32.@]
1380  *
1381  * BUGS
1382  *   Unimplemented
1383  */
1384 BOOL WINAPI SetConsoleInputExeNameA(LPCSTR name)
1385 {
1386     int         len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0);
1387     LPWSTR      xptr = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1388     BOOL        ret;
1389
1390     if (!xptr) return FALSE;
1391
1392     MultiByteToWideChar(CP_ACP, 0, name, -1, xptr, len);
1393     ret = SetConsoleInputExeNameW(xptr);
1394     HeapFree(GetProcessHeap(), 0, xptr);
1395
1396     return ret;
1397 }
1398
1399 /******************************************************************
1400  *              CONSOLE_DefaultHandler
1401  *
1402  * Final control event handler
1403  */
1404 static BOOL WINAPI CONSOLE_DefaultHandler(DWORD dwCtrlType)
1405 {
1406     FIXME("Terminating process %lx on event %lx\n", GetCurrentProcessId(), dwCtrlType);
1407     ExitProcess(0);
1408     /* should never go here */
1409     return TRUE;
1410 }
1411
1412 /******************************************************************************
1413  * SetConsoleCtrlHandler [KERNEL32.@]  Adds function to calling process list
1414  *
1415  * PARAMS
1416  *    func [I] Address of handler function
1417  *    add  [I] Handler to add or remove
1418  *
1419  * RETURNS
1420  *    Success: TRUE
1421  *    Failure: FALSE
1422  *
1423  * CHANGED
1424  * James Sutherland (JamesSutherland@gmx.de)
1425  * Added global variables console_ignore_ctrl_c and handlers[]
1426  * Does not yet do any error checking, or set LastError if failed.
1427  * This doesn't yet matter, since these handlers are not yet called...!
1428  */
1429
1430 struct ConsoleHandler {
1431     PHANDLER_ROUTINE            handler;
1432     struct ConsoleHandler*      next;
1433 };
1434
1435 static unsigned int             CONSOLE_IgnoreCtrlC = 0; /* FIXME: this should be inherited somehow */
1436 static struct ConsoleHandler    CONSOLE_DefaultConsoleHandler = {CONSOLE_DefaultHandler, NULL};
1437 static struct ConsoleHandler*   CONSOLE_Handlers = &CONSOLE_DefaultConsoleHandler;
1438
1439 static CRITICAL_SECTION CONSOLE_CritSect;
1440 static CRITICAL_SECTION_DEBUG critsect_debug =
1441 {
1442     0, 0, &CONSOLE_CritSect,
1443     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
1444       0, 0, { 0, (DWORD)(__FILE__ ": CONSOLE_CritSect") }
1445 };
1446 static CRITICAL_SECTION CONSOLE_CritSect = { &critsect_debug, -1, 0, 0, 0, 0 };
1447
1448 /*****************************************************************************/
1449
1450 BOOL WINAPI SetConsoleCtrlHandler(PHANDLER_ROUTINE func, BOOL add)
1451 {
1452     BOOL        ret = TRUE;
1453
1454     FIXME("(%p,%i) - no error checking or testing yet\n", func, add);
1455
1456     if (!func)
1457     {
1458         CONSOLE_IgnoreCtrlC = add;
1459     }
1460     else if (add)
1461     {
1462         struct ConsoleHandler*  ch = HeapAlloc(GetProcessHeap(), 0, sizeof(struct ConsoleHandler));
1463
1464         if (!ch) return FALSE;
1465         ch->handler = func;
1466         RtlEnterCriticalSection(&CONSOLE_CritSect);
1467         ch->next = CONSOLE_Handlers;
1468         CONSOLE_Handlers = ch;
1469         RtlLeaveCriticalSection(&CONSOLE_CritSect);
1470     }
1471     else
1472     {
1473         struct ConsoleHandler**  ch;
1474         RtlEnterCriticalSection(&CONSOLE_CritSect);
1475         for (ch = &CONSOLE_Handlers; *ch; *ch = (*ch)->next)
1476         {
1477             if ((*ch)->handler == func) break;
1478         }
1479         if (*ch)
1480         {
1481             struct ConsoleHandler*   rch = *ch;
1482
1483             /* sanity check */
1484             if (rch == &CONSOLE_DefaultConsoleHandler)
1485             {
1486                 ERR("Who's trying to remove default handler???\n");
1487                 ret = FALSE;
1488             }
1489             else
1490             {
1491                 rch = *ch;
1492                 *ch = (*ch)->next;
1493                 HeapFree(GetProcessHeap(), 0, rch);
1494             }
1495         }
1496         else
1497         {
1498             WARN("Attempt to remove non-installed CtrlHandler %p\n", func);
1499             ret = FALSE;
1500         }
1501         RtlLeaveCriticalSection(&CONSOLE_CritSect);
1502     }
1503     return ret;
1504 }
1505
1506 static WINE_EXCEPTION_FILTER(CONSOLE_CtrlEventHandler)
1507 {
1508     TRACE("(%lx)\n", GetExceptionCode());
1509     return EXCEPTION_EXECUTE_HANDLER;
1510 }
1511
1512 static DWORD WINAPI CONSOLE_HandleCtrlCEntry(void* pmt)
1513 {
1514     struct ConsoleHandler*  ch;
1515
1516     RtlEnterCriticalSection(&CONSOLE_CritSect);
1517     /* the debugger didn't continue... so, pass to ctrl handlers */
1518     for (ch = CONSOLE_Handlers; ch; ch = ch->next)
1519     {
1520         if (ch->handler((DWORD)pmt)) break;
1521     }
1522     RtlLeaveCriticalSection(&CONSOLE_CritSect);
1523     return 0;
1524 }
1525
1526 /******************************************************************
1527  *              CONSOLE_HandleCtrlC
1528  *
1529  * Check whether the shall manipulate CtrlC events
1530  */
1531 int     CONSOLE_HandleCtrlC(unsigned sig)
1532 {
1533     /* FIXME: better test whether a console is attached to this process ??? */
1534     extern    unsigned CONSOLE_GetNumHistoryEntries(void);
1535     if (CONSOLE_GetNumHistoryEntries() == (unsigned)-1) return 0;
1536     if (CONSOLE_IgnoreCtrlC) return 1;
1537
1538     /* try to pass the exception to the debugger
1539      * if it continues, there's nothing more to do
1540      * otherwise, we need to send the ctrl-event to the handlers
1541      */
1542     __TRY
1543     {
1544         RaiseException( DBG_CONTROL_C, 0, 0, NULL );
1545     }
1546     __EXCEPT(CONSOLE_CtrlEventHandler)
1547     {
1548         /* Create a separate thread to signal all the events. This would allow to
1549          * synchronize between setting the handlers and actually calling them
1550          */
1551         CreateThread(NULL, 0, CONSOLE_HandleCtrlCEntry, (void*)CTRL_C_EVENT, 0, NULL);
1552     }
1553     __ENDTRY;
1554     return 1;
1555 }
1556
1557 /******************************************************************************
1558  * GenerateConsoleCtrlEvent [KERNEL32.@] Simulate a CTRL-C or CTRL-BREAK
1559  *
1560  * PARAMS
1561  *    dwCtrlEvent        [I] Type of event
1562  *    dwProcessGroupID   [I] Process group ID to send event to
1563  *
1564  * RETURNS
1565  *    Success: True
1566  *    Failure: False (and *should* [but doesn't] set LastError)
1567  */
1568 BOOL WINAPI GenerateConsoleCtrlEvent(DWORD dwCtrlEvent,
1569                                      DWORD dwProcessGroupID)
1570 {
1571     BOOL ret;
1572
1573     TRACE("(%ld, %ld)\n", dwCtrlEvent, dwProcessGroupID);
1574
1575     if (dwCtrlEvent != CTRL_C_EVENT && dwCtrlEvent != CTRL_BREAK_EVENT)
1576     {
1577         ERR("Invalid event %ld for PGID %ld\n", dwCtrlEvent, dwProcessGroupID);
1578         return FALSE;
1579     }
1580
1581     SERVER_START_REQ( send_console_signal )
1582     {
1583         req->signal = dwCtrlEvent;
1584         req->group_id = dwProcessGroupID;
1585         ret = !wine_server_call_err( req );
1586     }
1587     SERVER_END_REQ;
1588
1589     return ret;
1590 }
1591
1592
1593 /******************************************************************************
1594  * CreateConsoleScreenBuffer [KERNEL32.@]  Creates a console screen buffer
1595  *
1596  * PARAMS
1597  *    dwDesiredAccess    [I] Access flag
1598  *    dwShareMode        [I] Buffer share mode
1599  *    sa                 [I] Security attributes
1600  *    dwFlags            [I] Type of buffer to create
1601  *    lpScreenBufferData [I] Reserved
1602  *
1603  * NOTES
1604  *    Should call SetLastError
1605  *
1606  * RETURNS
1607  *    Success: Handle to new console screen buffer
1608  *    Failure: INVALID_HANDLE_VALUE
1609  */
1610 HANDLE WINAPI CreateConsoleScreenBuffer(DWORD dwDesiredAccess, DWORD dwShareMode,
1611                                         LPSECURITY_ATTRIBUTES sa, DWORD dwFlags,
1612                                         LPVOID lpScreenBufferData)
1613 {
1614     HANDLE      ret = INVALID_HANDLE_VALUE;
1615
1616     TRACE("(%ld,%ld,%p,%ld,%p)\n",
1617           dwDesiredAccess, dwShareMode, sa, dwFlags, lpScreenBufferData);
1618
1619     if (dwFlags != CONSOLE_TEXTMODE_BUFFER || lpScreenBufferData != NULL)
1620     {
1621         SetLastError(ERROR_INVALID_PARAMETER);
1622         return INVALID_HANDLE_VALUE;
1623     }
1624
1625     SERVER_START_REQ(create_console_output)
1626     {
1627         req->handle_in = 0;
1628         req->access    = dwDesiredAccess;
1629         req->share     = dwShareMode;
1630         req->inherit   = (sa && sa->bInheritHandle);
1631         if (!wine_server_call_err( req )) ret = reply->handle_out;
1632     }
1633     SERVER_END_REQ;
1634
1635     return ret;
1636 }
1637
1638
1639 /***********************************************************************
1640  *           GetConsoleScreenBufferInfo   (KERNEL32.@)
1641  */
1642 BOOL WINAPI GetConsoleScreenBufferInfo(HANDLE hConsoleOutput, LPCONSOLE_SCREEN_BUFFER_INFO csbi)
1643 {
1644     BOOL        ret;
1645
1646     SERVER_START_REQ(get_console_output_info)
1647     {
1648         req->handle = console_handle_unmap(hConsoleOutput);
1649         if ((ret = !wine_server_call_err( req )))
1650         {
1651             csbi->dwSize.X              = reply->width;
1652             csbi->dwSize.Y              = reply->height;
1653             csbi->dwCursorPosition.X    = reply->cursor_x;
1654             csbi->dwCursorPosition.Y    = reply->cursor_y;
1655             csbi->wAttributes           = reply->attr;
1656             csbi->srWindow.Left         = reply->win_left;
1657             csbi->srWindow.Right        = reply->win_right;
1658             csbi->srWindow.Top          = reply->win_top;
1659             csbi->srWindow.Bottom       = reply->win_bottom;
1660             csbi->dwMaximumWindowSize.X = reply->max_width;
1661             csbi->dwMaximumWindowSize.Y = reply->max_height;
1662         }
1663     }
1664     SERVER_END_REQ;
1665
1666     TRACE("(%p,(%d,%d) (%d,%d) %d (%d,%d-%d,%d) (%d,%d)\n", 
1667           hConsoleOutput, csbi->dwSize.X, csbi->dwSize.Y,
1668           csbi->dwCursorPosition.X, csbi->dwCursorPosition.Y,
1669           csbi->wAttributes,
1670           csbi->srWindow.Left, csbi->srWindow.Top, csbi->srWindow.Right, csbi->srWindow.Bottom,
1671           csbi->dwMaximumWindowSize.X, csbi->dwMaximumWindowSize.Y);
1672
1673     return ret;
1674 }
1675
1676
1677 /******************************************************************************
1678  * SetConsoleActiveScreenBuffer [KERNEL32.@]  Sets buffer to current console
1679  *
1680  * RETURNS
1681  *    Success: TRUE
1682  *    Failure: FALSE
1683  */
1684 BOOL WINAPI SetConsoleActiveScreenBuffer(HANDLE hConsoleOutput)
1685 {
1686     BOOL ret;
1687
1688     TRACE("(%p)\n", hConsoleOutput);
1689
1690     SERVER_START_REQ( set_console_input_info )
1691     {
1692         req->handle    = 0;
1693         req->mask      = SET_CONSOLE_INPUT_INFO_ACTIVE_SB;
1694         req->active_sb = hConsoleOutput;
1695         ret = !wine_server_call_err( req );
1696     }
1697     SERVER_END_REQ;
1698     return ret;
1699 }
1700
1701
1702 /***********************************************************************
1703  *            GetConsoleMode   (KERNEL32.@)
1704  */
1705 BOOL WINAPI GetConsoleMode(HANDLE hcon, LPDWORD mode)
1706 {
1707     BOOL ret;
1708
1709     SERVER_START_REQ(get_console_mode)
1710     {
1711         req->handle = console_handle_unmap(hcon);
1712         ret = !wine_server_call_err( req );
1713         if (ret && mode) *mode = reply->mode;
1714     }
1715     SERVER_END_REQ;
1716     return ret;
1717 }
1718
1719
1720 /******************************************************************************
1721  * SetConsoleMode [KERNEL32.@]  Sets input mode of console's input buffer
1722  *
1723  * PARAMS
1724  *    hcon [I] Handle to console input or screen buffer
1725  *    mode [I] Input or output mode to set
1726  *
1727  * RETURNS
1728  *    Success: TRUE
1729  *    Failure: FALSE
1730  *
1731  *    mode:
1732  *      ENABLE_PROCESSED_INPUT  0x01
1733  *      ENABLE_LINE_INPUT       0x02
1734  *      ENABLE_ECHO_INPUT       0x04
1735  *      ENABLE_WINDOW_INPUT     0x08
1736  *      ENABLE_MOUSE_INPUT      0x10
1737  */
1738 BOOL WINAPI SetConsoleMode(HANDLE hcon, DWORD mode)
1739 {
1740     BOOL ret;
1741
1742     SERVER_START_REQ(set_console_mode)
1743     {
1744         req->handle = console_handle_unmap(hcon);
1745         req->mode = mode;
1746         ret = !wine_server_call_err( req );
1747     }
1748     SERVER_END_REQ;
1749     /* FIXME: when resetting a console input to editline mode, I think we should
1750      * empty the S_EditString buffer
1751      */
1752
1753     TRACE("(%p,%lx) retval == %d\n", hcon, mode, ret);
1754
1755     return ret;
1756 }
1757
1758
1759 /******************************************************************
1760  *              CONSOLE_WriteChars
1761  *
1762  * WriteConsoleOutput helper: hides server call semantics
1763  * writes a string at a given pos with standard attribute
1764  */
1765 int CONSOLE_WriteChars(HANDLE hCon, LPCWSTR lpBuffer, int nc, COORD* pos)
1766 {
1767     int written = -1;
1768
1769     if (!nc) return 0;
1770
1771     SERVER_START_REQ( write_console_output )
1772     {
1773         req->handle = console_handle_unmap(hCon);
1774         req->x      = pos->X;
1775         req->y      = pos->Y;
1776         req->mode   = CHAR_INFO_MODE_TEXTSTDATTR;
1777         req->wrap   = FALSE;
1778         wine_server_add_data( req, lpBuffer, nc * sizeof(WCHAR) );
1779         if (!wine_server_call_err( req )) written = reply->written;
1780     }
1781     SERVER_END_REQ;
1782
1783     if (written > 0) pos->X += written;
1784     return written;
1785 }
1786
1787 /******************************************************************
1788  *              next_line
1789  *
1790  * WriteConsoleOutput helper: handles passing to next line (+scrolling if necessary)
1791  *
1792  */
1793 static int      next_line(HANDLE hCon, CONSOLE_SCREEN_BUFFER_INFO* csbi)
1794 {
1795     SMALL_RECT  src;
1796     CHAR_INFO   ci;
1797     COORD       dst;
1798
1799     csbi->dwCursorPosition.X = 0;
1800     csbi->dwCursorPosition.Y++;
1801
1802     if (csbi->dwCursorPosition.Y < csbi->dwSize.Y) return 1;
1803
1804     src.Top    = 1;
1805     src.Bottom = csbi->dwSize.Y - 1;
1806     src.Left   = 0;
1807     src.Right  = csbi->dwSize.X - 1;
1808
1809     dst.X      = 0;
1810     dst.Y      = 0;
1811
1812     ci.Attributes = csbi->wAttributes;
1813     ci.Char.UnicodeChar = ' ';
1814
1815     csbi->dwCursorPosition.Y--;
1816     if (!ScrollConsoleScreenBufferW(hCon, &src, NULL, dst, &ci))
1817         return 0;
1818     return 1;
1819 }
1820
1821 /******************************************************************
1822  *              write_block
1823  *
1824  * WriteConsoleOutput helper: writes a block of non special characters
1825  * Block can spread on several lines, and wrapping, if needed, is
1826  * handled
1827  *
1828  */
1829 static int      write_block(HANDLE hCon, CONSOLE_SCREEN_BUFFER_INFO* csbi,
1830                             DWORD mode, LPCWSTR ptr, int len)
1831 {
1832     int blk;    /* number of chars to write on current line */
1833     int done;   /* number of chars already written */
1834
1835     if (len <= 0) return 1;
1836
1837     if (mode & ENABLE_WRAP_AT_EOL_OUTPUT) /* writes remaining on next line */
1838     {
1839         for (done = 0; done < len; done += blk)
1840         {
1841             blk = min(len - done, csbi->dwSize.X - csbi->dwCursorPosition.X);
1842
1843             if (CONSOLE_WriteChars(hCon, ptr + done, blk, &csbi->dwCursorPosition) != blk)
1844                 return 0;
1845             if (csbi->dwCursorPosition.X == csbi->dwSize.X && !next_line(hCon, csbi))
1846                 return 0;
1847         }
1848     }
1849     else
1850     {
1851         int     pos = csbi->dwCursorPosition.X;
1852         /* FIXME: we could reduce the number of loops
1853          * but, in most cases we wouldn't gain lots of time (it would only
1854          * happen if we're asked to overwrite more than twice the part of the line,
1855          * which is unlikely
1856          */
1857         for (blk = done = 0; done < len; done += blk)
1858         {
1859             blk = min(len - done, csbi->dwSize.X - csbi->dwCursorPosition.X);
1860
1861             csbi->dwCursorPosition.X = pos;
1862             if (CONSOLE_WriteChars(hCon, ptr + done, blk, &csbi->dwCursorPosition) != blk)
1863                 return 0;
1864         }
1865     }
1866
1867     return 1;
1868 }
1869
1870 /***********************************************************************
1871  *            WriteConsoleW   (KERNEL32.@)
1872  */
1873 BOOL WINAPI WriteConsoleW(HANDLE hConsoleOutput, LPCVOID lpBuffer, DWORD nNumberOfCharsToWrite,
1874                           LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved)
1875 {
1876     DWORD                       mode;
1877     DWORD                       nw = 0;
1878     const WCHAR*                psz = lpBuffer;
1879     CONSOLE_SCREEN_BUFFER_INFO  csbi;
1880     int                         k, first = 0;
1881
1882     TRACE("%p %s %ld %p %p\n",
1883           hConsoleOutput, debugstr_wn(lpBuffer, nNumberOfCharsToWrite),
1884           nNumberOfCharsToWrite, lpNumberOfCharsWritten, lpReserved);
1885
1886     if (lpNumberOfCharsWritten) *lpNumberOfCharsWritten = 0;
1887
1888     if (!GetConsoleMode(hConsoleOutput, &mode) ||
1889         !GetConsoleScreenBufferInfo(hConsoleOutput, &csbi))
1890         return FALSE;
1891
1892     if (mode & ENABLE_PROCESSED_OUTPUT)
1893     {
1894         int     i;
1895
1896         for (i = 0; i < nNumberOfCharsToWrite; i++)
1897         {
1898             switch (psz[i])
1899             {
1900             case '\b': case '\t': case '\n': case '\a': case '\r':
1901                 /* don't handle here the i-th char... done below */
1902                 if ((k = i - first) > 0)
1903                 {
1904                     if (!write_block(hConsoleOutput, &csbi, mode, &psz[first], k))
1905                         goto the_end;
1906                     nw += k;
1907                 }
1908                 first = i + 1;
1909                 nw++;
1910             }
1911             switch (psz[i])
1912             {
1913             case '\b':
1914                 if (csbi.dwCursorPosition.X > 0) csbi.dwCursorPosition.X--;
1915                 break;
1916             case '\t':
1917                 {
1918                     WCHAR tmp[8] = {' ',' ',' ',' ',' ',' ',' ',' '};
1919
1920                     if (!write_block(hConsoleOutput, &csbi, mode, tmp,
1921                                      ((csbi.dwCursorPosition.X + 8) & ~7) - csbi.dwCursorPosition.X))
1922                         goto the_end;
1923                 }
1924                 break;
1925             case '\n':
1926                 next_line(hConsoleOutput, &csbi);
1927                 break;
1928             case '\a':
1929                 Beep(400, 300);
1930                 break;
1931             case '\r':
1932                 csbi.dwCursorPosition.X = 0;
1933                 break;
1934             default:
1935                 break;
1936             }
1937         }
1938     }
1939
1940     /* write the remaining block (if any) if processed output is enabled, or the
1941      * entire buffer otherwise
1942      */
1943     if ((k = nNumberOfCharsToWrite - first) > 0)
1944     {
1945         if (!write_block(hConsoleOutput, &csbi, mode, &psz[first], k))
1946             goto the_end;
1947         nw += k;
1948     }
1949
1950  the_end:
1951     SetConsoleCursorPosition(hConsoleOutput, csbi.dwCursorPosition);
1952     if (lpNumberOfCharsWritten) *lpNumberOfCharsWritten = nw;
1953     return nw != 0;
1954 }
1955
1956
1957 /***********************************************************************
1958  *            WriteConsoleA   (KERNEL32.@)
1959  */
1960 BOOL WINAPI WriteConsoleA(HANDLE hConsoleOutput, LPCVOID lpBuffer, DWORD nNumberOfCharsToWrite,
1961                           LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved)
1962 {
1963     BOOL        ret;
1964     LPWSTR      xstring;
1965     DWORD       n;
1966
1967     n = MultiByteToWideChar(CP_ACP, 0, lpBuffer, nNumberOfCharsToWrite, NULL, 0);
1968
1969     if (lpNumberOfCharsWritten) *lpNumberOfCharsWritten = 0;
1970     xstring = HeapAlloc(GetProcessHeap(), 0, n * sizeof(WCHAR));
1971     if (!xstring) return 0;
1972
1973     MultiByteToWideChar(CP_ACP, 0, lpBuffer, nNumberOfCharsToWrite, xstring, n);
1974
1975     ret = WriteConsoleW(hConsoleOutput, xstring, n, lpNumberOfCharsWritten, 0);
1976
1977     HeapFree(GetProcessHeap(), 0, xstring);
1978
1979     return ret;
1980 }
1981
1982 /******************************************************************************
1983  * SetConsoleCursorPosition [KERNEL32.@]
1984  * Sets the cursor position in console
1985  *
1986  * PARAMS
1987  *    hConsoleOutput   [I] Handle of console screen buffer
1988  *    dwCursorPosition [I] New cursor position coordinates
1989  *
1990  * RETURNS STD
1991  */
1992 BOOL WINAPI SetConsoleCursorPosition(HANDLE hcon, COORD pos)
1993 {
1994     BOOL                        ret;
1995     CONSOLE_SCREEN_BUFFER_INFO  csbi;
1996     int                         do_move = 0;
1997     int                         w, h;
1998
1999     TRACE("%p %d %d\n", hcon, pos.X, pos.Y);
2000
2001     SERVER_START_REQ(set_console_output_info)
2002     {
2003         req->handle         = console_handle_unmap(hcon);
2004         req->cursor_x       = pos.X;
2005         req->cursor_y       = pos.Y;
2006         req->mask           = SET_CONSOLE_OUTPUT_INFO_CURSOR_POS;
2007         ret = !wine_server_call_err( req );
2008     }
2009     SERVER_END_REQ;
2010
2011     if (!ret || !GetConsoleScreenBufferInfo(hcon, &csbi))
2012         return FALSE;
2013
2014     /* if cursor is no longer visible, scroll the visible window... */
2015     w = csbi.srWindow.Right - csbi.srWindow.Left + 1;
2016     h = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
2017     if (pos.X < csbi.srWindow.Left)
2018     {
2019         csbi.srWindow.Left   = min(pos.X, csbi.dwSize.X - w);
2020         do_move++;
2021     }
2022     else if (pos.X > csbi.srWindow.Right)
2023     {
2024         csbi.srWindow.Left   = max(pos.X, w) - w + 1;
2025         do_move++;
2026     }
2027     csbi.srWindow.Right  = csbi.srWindow.Left + w - 1;
2028
2029     if (pos.Y < csbi.srWindow.Top)
2030     {
2031         csbi.srWindow.Top    = min(pos.Y, csbi.dwSize.Y - h);
2032         do_move++;
2033     }
2034     else if (pos.Y > csbi.srWindow.Bottom)
2035     {
2036         csbi.srWindow.Top   = max(pos.Y, h) - h + 1;
2037         do_move++;
2038     }
2039     csbi.srWindow.Bottom = csbi.srWindow.Top + h - 1;
2040
2041     ret = (do_move) ? SetConsoleWindowInfo(hcon, TRUE, &csbi.srWindow) : TRUE;
2042
2043     return ret;
2044 }
2045
2046 /******************************************************************************
2047  * GetConsoleCursorInfo [KERNEL32.@]  Gets size and visibility of console
2048  *
2049  * PARAMS
2050  *    hcon  [I] Handle to console screen buffer
2051  *    cinfo [O] Address of cursor information
2052  *
2053  * RETURNS
2054  *    Success: TRUE
2055  *    Failure: FALSE
2056  */
2057 BOOL WINAPI GetConsoleCursorInfo(HANDLE hCon, LPCONSOLE_CURSOR_INFO cinfo)
2058 {
2059     BOOL ret;
2060
2061     SERVER_START_REQ(get_console_output_info)
2062     {
2063         req->handle = console_handle_unmap(hCon);
2064         ret = !wine_server_call_err( req );
2065         if (ret && cinfo)
2066         {
2067             cinfo->dwSize = reply->cursor_size;
2068             cinfo->bVisible = reply->cursor_visible;
2069         }
2070     }
2071     SERVER_END_REQ;
2072
2073     TRACE("(%p) returning (%ld,%d)\n", hCon, cinfo->dwSize, cinfo->bVisible);
2074     return ret;
2075 }
2076
2077
2078 /******************************************************************************
2079  * SetConsoleCursorInfo [KERNEL32.@]  Sets size and visibility of cursor
2080  *
2081  * PARAMS
2082  *      hcon    [I] Handle to console screen buffer
2083  *      cinfo   [I] Address of cursor information
2084  * RETURNS
2085  *    Success: TRUE
2086  *    Failure: FALSE
2087  */
2088 BOOL WINAPI SetConsoleCursorInfo(HANDLE hCon, LPCONSOLE_CURSOR_INFO cinfo)
2089 {
2090     BOOL ret;
2091
2092     TRACE("(%p,%ld,%d)\n", hCon, cinfo->dwSize, cinfo->bVisible);
2093     SERVER_START_REQ(set_console_output_info)
2094     {
2095         req->handle         = console_handle_unmap(hCon);
2096         req->cursor_size    = cinfo->dwSize;
2097         req->cursor_visible = cinfo->bVisible;
2098         req->mask           = SET_CONSOLE_OUTPUT_INFO_CURSOR_GEOM;
2099         ret = !wine_server_call_err( req );
2100     }
2101     SERVER_END_REQ;
2102     return ret;
2103 }
2104
2105
2106 /******************************************************************************
2107  * SetConsoleWindowInfo [KERNEL32.@]  Sets size and position of console
2108  *
2109  * PARAMS
2110  *      hcon            [I] Handle to console screen buffer
2111  *      bAbsolute       [I] Coordinate type flag
2112  *      window          [I] Address of new window rectangle
2113  * RETURNS
2114  *    Success: TRUE
2115  *    Failure: FALSE
2116  */
2117 BOOL WINAPI SetConsoleWindowInfo(HANDLE hCon, BOOL bAbsolute, LPSMALL_RECT window)
2118 {
2119     SMALL_RECT  p = *window;
2120     BOOL        ret;
2121
2122     TRACE("(%p,%d,(%d,%d-%d,%d))\n", hCon, bAbsolute, p.Left, p.Top, p.Right, p.Bottom);
2123
2124     if (!bAbsolute)
2125     {
2126         CONSOLE_SCREEN_BUFFER_INFO      csbi;
2127
2128         if (!GetConsoleScreenBufferInfo(hCon, &csbi))
2129             return FALSE;
2130         p.Left   += csbi.srWindow.Left;
2131         p.Top    += csbi.srWindow.Top;
2132         p.Right  += csbi.srWindow.Right;
2133         p.Bottom += csbi.srWindow.Bottom;
2134     }
2135     SERVER_START_REQ(set_console_output_info)
2136     {
2137         req->handle         = console_handle_unmap(hCon);
2138         req->win_left       = p.Left;
2139         req->win_top        = p.Top;
2140         req->win_right      = p.Right;
2141         req->win_bottom     = p.Bottom;
2142         req->mask           = SET_CONSOLE_OUTPUT_INFO_DISPLAY_WINDOW;
2143         ret = !wine_server_call_err( req );
2144     }
2145     SERVER_END_REQ;
2146
2147     return ret;
2148 }
2149
2150
2151 /******************************************************************************
2152  * SetConsoleTextAttribute [KERNEL32.@]  Sets colors for text
2153  *
2154  * Sets the foreground and background color attributes of characters
2155  * written to the screen buffer.
2156  *
2157  * RETURNS
2158  *    Success: TRUE
2159  *    Failure: FALSE
2160  */
2161 BOOL WINAPI SetConsoleTextAttribute(HANDLE hConsoleOutput, WORD wAttr)
2162 {
2163     BOOL ret;
2164
2165     TRACE("(%p,%d)\n", hConsoleOutput, wAttr);
2166     SERVER_START_REQ(set_console_output_info)
2167     {
2168         req->handle = console_handle_unmap(hConsoleOutput);
2169         req->attr   = wAttr;
2170         req->mask   = SET_CONSOLE_OUTPUT_INFO_ATTR;
2171         ret = !wine_server_call_err( req );
2172     }
2173     SERVER_END_REQ;
2174     return ret;
2175 }
2176
2177
2178 /******************************************************************************
2179  * SetConsoleScreenBufferSize [KERNEL32.@]  Changes size of console
2180  *
2181  * PARAMS
2182  *    hConsoleOutput [I] Handle to console screen buffer
2183  *    dwSize         [I] New size in character rows and cols
2184  *
2185  * RETURNS
2186  *    Success: TRUE
2187  *    Failure: FALSE
2188  */
2189 BOOL WINAPI SetConsoleScreenBufferSize(HANDLE hConsoleOutput, COORD dwSize)
2190 {
2191     BOOL ret;
2192
2193     TRACE("(%p,(%d,%d))\n", hConsoleOutput, dwSize.X, dwSize.Y);
2194     SERVER_START_REQ(set_console_output_info)
2195     {
2196         req->handle = console_handle_unmap(hConsoleOutput);
2197         req->width  = dwSize.X;
2198         req->height = dwSize.Y;
2199         req->mask   = SET_CONSOLE_OUTPUT_INFO_SIZE;
2200         ret = !wine_server_call_err( req );
2201     }
2202     SERVER_END_REQ;
2203     return ret;
2204 }
2205
2206
2207 /******************************************************************************
2208  * ScrollConsoleScreenBufferA [KERNEL32.@]
2209  *
2210  */
2211 BOOL WINAPI ScrollConsoleScreenBufferA(HANDLE hConsoleOutput, LPSMALL_RECT lpScrollRect,
2212                                        LPSMALL_RECT lpClipRect, COORD dwDestOrigin,
2213                                        LPCHAR_INFO lpFill)
2214 {
2215     CHAR_INFO   ciw;
2216
2217     ciw.Attributes = lpFill->Attributes;
2218     MultiByteToWideChar(CP_ACP, 0, &lpFill->Char.AsciiChar, 1, &ciw.Char.UnicodeChar, 1);
2219
2220     return ScrollConsoleScreenBufferW(hConsoleOutput, lpScrollRect, lpClipRect,
2221                                       dwDestOrigin, &ciw);
2222 }
2223
2224 /******************************************************************
2225  *              CONSOLE_FillLineUniform
2226  *
2227  * Helper function for ScrollConsoleScreenBufferW
2228  * Fills a part of a line with a constant character info
2229  */
2230 void CONSOLE_FillLineUniform(HANDLE hConsoleOutput, int i, int j, int len, LPCHAR_INFO lpFill)
2231 {
2232     SERVER_START_REQ( fill_console_output )
2233     {
2234         req->handle    = console_handle_unmap(hConsoleOutput);
2235         req->mode      = CHAR_INFO_MODE_TEXTATTR;
2236         req->x         = i;
2237         req->y         = j;
2238         req->count     = len;
2239         req->wrap      = FALSE;
2240         req->data.ch   = lpFill->Char.UnicodeChar;
2241         req->data.attr = lpFill->Attributes;
2242         wine_server_call_err( req );
2243     }
2244     SERVER_END_REQ;
2245 }
2246
2247 /******************************************************************************
2248  * ScrollConsoleScreenBufferW [KERNEL32.@]
2249  *
2250  */
2251
2252 BOOL WINAPI ScrollConsoleScreenBufferW(HANDLE hConsoleOutput, LPSMALL_RECT lpScrollRect,
2253                                        LPSMALL_RECT lpClipRect, COORD dwDestOrigin,
2254                                        LPCHAR_INFO lpFill)
2255 {
2256     SMALL_RECT                  dst;
2257     DWORD                       ret;
2258     int                         i, j;
2259     int                         start = -1;
2260     SMALL_RECT                  clip;
2261     CONSOLE_SCREEN_BUFFER_INFO  csbi;
2262     BOOL                        inside;
2263
2264     if (lpClipRect)
2265         TRACE("(%p,(%d,%d-%d,%d),(%d,%d-%d,%d),%d-%d,%p)\n", hConsoleOutput,
2266               lpScrollRect->Left, lpScrollRect->Top,
2267               lpScrollRect->Right, lpScrollRect->Bottom,
2268               lpClipRect->Left, lpClipRect->Top,
2269               lpClipRect->Right, lpClipRect->Bottom,
2270               dwDestOrigin.X, dwDestOrigin.Y, lpFill);
2271     else
2272         TRACE("(%p,(%d,%d-%d,%d),(nil),%d-%d,%p)\n", hConsoleOutput,
2273               lpScrollRect->Left, lpScrollRect->Top,
2274               lpScrollRect->Right, lpScrollRect->Bottom,
2275               dwDestOrigin.X, dwDestOrigin.Y, lpFill);
2276
2277     if (!GetConsoleScreenBufferInfo(hConsoleOutput, &csbi))
2278         return FALSE;
2279
2280     /* step 1: get dst rect */
2281     dst.Left = dwDestOrigin.X;
2282     dst.Top = dwDestOrigin.Y;
2283     dst.Right = dst.Left + (lpScrollRect->Right - lpScrollRect->Left);
2284     dst.Bottom = dst.Top + (lpScrollRect->Bottom - lpScrollRect->Top);
2285
2286     /* step 2a: compute the final clip rect (optional passed clip and screen buffer limits */
2287     if (lpClipRect)
2288     {
2289         clip.Left   = max(0, lpClipRect->Left);
2290         clip.Right  = min(csbi.dwSize.X - 1, lpClipRect->Right);
2291         clip.Top    = max(0, lpClipRect->Top);
2292         clip.Bottom = min(csbi.dwSize.Y - 1, lpClipRect->Bottom);
2293     }
2294     else
2295     {
2296         clip.Left   = 0;
2297         clip.Right  = csbi.dwSize.X - 1;
2298         clip.Top    = 0;
2299         clip.Bottom = csbi.dwSize.Y - 1;
2300     }
2301     if (clip.Left > clip.Right || clip.Top > clip.Bottom) return FALSE;
2302
2303     /* step 2b: clip dst rect */
2304     if (dst.Left   < clip.Left  ) dst.Left   = clip.Left;
2305     if (dst.Top    < clip.Top   ) dst.Top    = clip.Top;
2306     if (dst.Right  > clip.Right ) dst.Right  = clip.Right;
2307     if (dst.Bottom > clip.Bottom) dst.Bottom = clip.Bottom;
2308
2309     /* step 3: transfer the bits */
2310     SERVER_START_REQ(move_console_output)
2311     {
2312         req->handle = console_handle_unmap(hConsoleOutput);
2313         req->x_src = lpScrollRect->Left;
2314         req->y_src = lpScrollRect->Top;
2315         req->x_dst = dst.Left;
2316         req->y_dst = dst.Top;
2317         req->w = dst.Right - dst.Left + 1;
2318         req->h = dst.Bottom - dst.Top + 1;
2319         ret = !wine_server_call_err( req );
2320     }
2321     SERVER_END_REQ;
2322
2323     if (!ret) return FALSE;
2324
2325     /* step 4: clean out the exposed part */
2326
2327     /* have to write cell [i,j] if it is not in dst rect (because it has already
2328      * been written to by the scroll) and is in clip (we shall not write
2329      * outside of clip)
2330      */
2331     for (j = max(lpScrollRect->Top, clip.Top); j <= min(lpScrollRect->Bottom, clip.Bottom); j++)
2332     {
2333         inside = dst.Top <= j && j <= dst.Bottom;
2334         start = -1;
2335         for (i = max(lpScrollRect->Left, clip.Left); i <= min(lpScrollRect->Right, clip.Right); i++)
2336         {
2337             if (inside && dst.Left <= i && i <= dst.Right)
2338             {
2339                 if (start != -1)
2340                 {
2341                     CONSOLE_FillLineUniform(hConsoleOutput, start, j, i - start, lpFill);
2342                     start = -1;
2343                 }
2344             }
2345             else
2346             {
2347                 if (start == -1) start = i;
2348             }
2349         }
2350         if (start != -1)
2351             CONSOLE_FillLineUniform(hConsoleOutput, start, j, i - start, lpFill);
2352     }
2353
2354     return TRUE;
2355 }
2356
2357
2358 /* ====================================================================
2359  *
2360  * Console manipulation functions
2361  *
2362  * ====================================================================*/
2363
2364 /* some missing functions...
2365  * FIXME: those are likely to be defined as undocumented function in kernel32 (or part of them)
2366  * should get the right API and implement them
2367  *      GetConsoleCommandHistory[AW] (dword dword dword)
2368  *      GetConsoleCommandHistoryLength[AW]
2369  *      SetConsoleCommandHistoryMode
2370  *      SetConsoleNumberOfCommands[AW]
2371  */
2372 int CONSOLE_GetHistory(int idx, WCHAR* buf, int buf_len)
2373 {
2374     int len = 0;
2375
2376     SERVER_START_REQ( get_console_input_history )
2377     {
2378         req->handle = 0;
2379         req->index = idx;
2380         if (buf && buf_len > 1)
2381         {
2382             wine_server_set_reply( req, buf, (buf_len - 1) * sizeof(WCHAR) );
2383         }
2384         if (!wine_server_call_err( req ))
2385         {
2386             if (buf) buf[wine_server_reply_size(reply) / sizeof(WCHAR)] = 0;
2387             len = reply->total / sizeof(WCHAR) + 1;
2388         }
2389     }
2390     SERVER_END_REQ;
2391     return len;
2392 }
2393
2394 /******************************************************************
2395  *              CONSOLE_AppendHistory
2396  *
2397  *
2398  */
2399 BOOL    CONSOLE_AppendHistory(const WCHAR* ptr)
2400 {
2401     size_t      len = strlenW(ptr);
2402     BOOL        ret;
2403
2404     while (len && (ptr[len - 1] == '\n' || ptr[len - 1] == '\r')) len--;
2405
2406     SERVER_START_REQ( append_console_input_history )
2407     {
2408         req->handle = 0;
2409         wine_server_add_data( req, ptr, len * sizeof(WCHAR) );
2410         ret = !wine_server_call_err( req );
2411     }
2412     SERVER_END_REQ;
2413     return ret;
2414 }
2415
2416 /******************************************************************
2417  *              CONSOLE_GetNumHistoryEntries
2418  *
2419  *
2420  */
2421 unsigned CONSOLE_GetNumHistoryEntries(void)
2422 {
2423     unsigned ret = -1;
2424     SERVER_START_REQ(get_console_input_info)
2425     {
2426         req->handle = 0;
2427         if (!wine_server_call_err( req )) ret = reply->history_index;
2428     }
2429     SERVER_END_REQ;
2430     return ret;
2431 }
2432
2433 /******************************************************************
2434  *              CONSOLE_GetEditionMode
2435  *
2436  *
2437  */
2438 BOOL CONSOLE_GetEditionMode(HANDLE hConIn, int* mode)
2439 {
2440     unsigned ret = FALSE;
2441     SERVER_START_REQ(get_console_input_info)
2442     {
2443         req->handle = console_handle_unmap(hConIn);
2444         if ((ret = !wine_server_call_err( req )))
2445             *mode = reply->edition_mode;
2446     }
2447     SERVER_END_REQ;
2448     return ret;
2449 }