Fixed license text.
[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 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
33 #include <stdio.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <assert.h>
37
38 #include "winbase.h"
39 #include "winnls.h"
40 #include "winerror.h"
41 #include "wincon.h"
42 #include "wine/server.h"
43 #include "wine/exception.h"
44 #include "wine/unicode.h"
45 #include "wine/debug.h"
46
47 WINE_DEFAULT_DEBUG_CHANNEL(console);
48
49
50 static UINT console_input_codepage;
51 static UINT console_output_codepage;
52
53 /* map input records to ASCII */
54 static void input_records_WtoA( INPUT_RECORD *buffer, int count )
55 {
56     int i;
57     char ch;
58
59     for (i = 0; i < count; i++)
60     {
61         if (buffer[i].EventType != KEY_EVENT) continue;
62         WideCharToMultiByte( GetConsoleCP(), 0,
63                              &buffer[i].Event.KeyEvent.uChar.UnicodeChar, 1, &ch, 1, NULL, NULL );
64         buffer[i].Event.KeyEvent.uChar.AsciiChar = ch;
65     }
66 }
67
68 /* map input records to Unicode */
69 static void input_records_AtoW( INPUT_RECORD *buffer, int count )
70 {
71     int i;
72     WCHAR ch;
73
74     for (i = 0; i < count; i++)
75     {
76         if (buffer[i].EventType != KEY_EVENT) continue;
77         MultiByteToWideChar( GetConsoleCP(), 0,
78                              &buffer[i].Event.KeyEvent.uChar.AsciiChar, 1, &ch, 1 );
79         buffer[i].Event.KeyEvent.uChar.UnicodeChar = ch;
80     }
81 }
82
83 /* map char infos to ASCII */
84 static void char_info_WtoA( CHAR_INFO *buffer, int count )
85 {
86     char ch;
87
88     while (count-- > 0)
89     {
90         WideCharToMultiByte( GetConsoleOutputCP(), 0, &buffer->Char.UnicodeChar, 1,
91                              &ch, 1, NULL, NULL );
92         buffer->Char.AsciiChar = ch;
93         buffer++;
94     }
95 }
96
97 /* map char infos to Unicode */
98 static void char_info_AtoW( CHAR_INFO *buffer, int count )
99 {
100     WCHAR ch;
101
102     while (count-- > 0)
103     {
104         MultiByteToWideChar( GetConsoleOutputCP(), 0, &buffer->Char.AsciiChar, 1, &ch, 1 );
105         buffer->Char.UnicodeChar = ch;
106         buffer++;
107     }
108 }
109
110
111 /******************************************************************************
112  * GetConsoleCP [KERNEL32.@]  Returns the OEM code page for the console
113  *
114  * RETURNS
115  *    Code page code
116  */
117 UINT WINAPI GetConsoleCP(VOID)
118 {
119     if (!console_input_codepage) console_input_codepage = GetOEMCP();
120     return console_input_codepage;
121 }
122
123
124 /******************************************************************************
125  *  SetConsoleCP         [KERNEL32.@]
126  */
127 BOOL WINAPI SetConsoleCP(UINT cp)
128 {
129     if (!IsValidCodePage( cp )) return FALSE;
130     console_input_codepage = cp;
131     return TRUE;
132 }
133
134
135 /***********************************************************************
136  *            GetConsoleOutputCP   (KERNEL32.@)
137  */
138 UINT WINAPI GetConsoleOutputCP(VOID)
139 {
140     if (!console_output_codepage) console_output_codepage = GetOEMCP();
141     return console_output_codepage;
142 }
143
144
145 /******************************************************************************
146  * SetConsoleOutputCP [KERNEL32.@]  Set the output codepage used by the console
147  *
148  * PARAMS
149  *    cp [I] code page to set
150  *
151  * RETURNS
152  *    Success: TRUE
153  *    Failure: FALSE
154  */
155 BOOL WINAPI SetConsoleOutputCP(UINT cp)
156 {
157     if (!IsValidCodePage( cp )) return FALSE;
158     console_output_codepage = cp;
159     return TRUE;
160 }
161
162
163 /******************************************************************************
164  * WriteConsoleInputA [KERNEL32.@]
165  */
166 BOOL WINAPI WriteConsoleInputA( HANDLE handle, const INPUT_RECORD *buffer,
167                                 DWORD count, LPDWORD written )
168 {
169     INPUT_RECORD *recW;
170     BOOL ret;
171
172     if (!(recW = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*recW) ))) return FALSE;
173     memcpy( recW, buffer, count*sizeof(*recW) );
174     input_records_AtoW( recW, count );
175     ret = WriteConsoleInputW( handle, recW, count, written );
176     HeapFree( GetProcessHeap(), 0, recW );
177     return ret;
178 }
179
180
181 /******************************************************************************
182  * WriteConsoleInputW [KERNEL32.@]
183  */
184 BOOL WINAPI WriteConsoleInputW( HANDLE handle, const INPUT_RECORD *buffer,
185                                 DWORD count, LPDWORD written )
186 {
187     BOOL ret;
188
189     TRACE("(%d,%p,%ld,%p)\n", handle, buffer, count, written);
190
191     if (written) *written = 0;
192     SERVER_START_REQ( write_console_input )
193     {
194         req->handle = handle;
195         wine_server_add_data( req, buffer, count * sizeof(INPUT_RECORD) );
196         if ((ret = !wine_server_call_err( req )))
197         {
198             if (written) *written = reply->written;
199         }
200     }
201     SERVER_END_REQ;
202     return ret;
203 }
204
205
206 /***********************************************************************
207  *            WriteConsoleOutputA   (KERNEL32.@)
208  */
209 BOOL WINAPI WriteConsoleOutputA( HANDLE hConsoleOutput, const CHAR_INFO *lpBuffer,
210                                  COORD size, COORD coord, LPSMALL_RECT region )
211 {
212     int y;
213     BOOL ret;
214     COORD new_size, new_coord;
215     CHAR_INFO *ciw;
216
217     new_size.X = min( region->Right - region->Left + 1, size.X - coord.X );
218     new_size.Y = min( region->Bottom - region->Top + 1, size.Y - coord.Y );
219
220     if (new_size.X <= 0 || new_size.Y <= 0)
221     {
222         region->Bottom = region->Top + new_size.Y - 1;
223         region->Right = region->Left + new_size.X - 1;
224         return TRUE;
225     }
226
227     /* only copy the useful rectangle */
228     if (!(ciw = HeapAlloc( GetProcessHeap(), 0, sizeof(CHAR_INFO) * new_size.X * new_size.Y )))
229         return FALSE;
230     for (y = 0; y < new_size.Y; y++)
231     {
232         memcpy( &ciw[y * new_size.X], &lpBuffer[(y + coord.Y) * size.X + coord.X],
233                 new_size.X * sizeof(CHAR_INFO) );
234         char_info_AtoW( ciw, new_size.X );
235     }
236     new_coord.X = new_coord.Y = 0;
237     ret = WriteConsoleOutputW( hConsoleOutput, ciw, new_size, new_coord, region );
238     if (ciw) HeapFree( GetProcessHeap(), 0, ciw );
239     return ret;
240 }
241
242
243 /***********************************************************************
244  *            WriteConsoleOutputW   (KERNEL32.@)
245  */
246 BOOL WINAPI WriteConsoleOutputW( HANDLE hConsoleOutput, const CHAR_INFO *lpBuffer,
247                                  COORD size, COORD coord, LPSMALL_RECT region )
248 {
249     int width, height, y;
250     BOOL ret = TRUE;
251
252     TRACE("(%x,%p,(%d,%d),(%d,%d),(%d,%dx%d,%d)\n",
253           hConsoleOutput, lpBuffer, size.X, size.Y, coord.X, coord.Y,
254           region->Left, region->Top, region->Right, region->Bottom);
255
256     width = min( region->Right - region->Left + 1, size.X - coord.X );
257     height = min( region->Bottom - region->Top + 1, size.Y - coord.Y );
258
259     if (width > 0 && height > 0)
260     {
261         for (y = 0; y < height; y++)
262         {
263             SERVER_START_REQ( write_console_output )
264             {
265                 req->handle = hConsoleOutput;
266                 req->x      = region->Left;
267                 req->y      = region->Top + y;
268                 req->mode   = CHAR_INFO_MODE_TEXTATTR;
269                 req->wrap   = FALSE;
270                 wine_server_add_data( req, &lpBuffer[(y + coord.Y) * size.X + coord.X],
271                                       width * sizeof(CHAR_INFO));
272                 if ((ret = !wine_server_call_err( req )))
273                 {
274                     width  = min( width, reply->width - region->Left );
275                     height = min( height, reply->height - region->Top );
276                 }
277             }
278             SERVER_END_REQ;
279             if (!ret) break;
280         }
281     }
282     region->Bottom = region->Top + height - 1;
283     region->Right = region->Left + width - 1;
284     return ret;
285 }
286
287
288 /******************************************************************************
289  * WriteConsoleOutputCharacterA [KERNEL32.@]  Copies character to consecutive
290  *                                            cells in the console screen buffer
291  *
292  * PARAMS
293  *    hConsoleOutput    [I] Handle to screen buffer
294  *    str               [I] Pointer to buffer with chars to write
295  *    length            [I] Number of cells to write to
296  *    coord             [I] Coords of first cell
297  *    lpNumCharsWritten [O] Pointer to number of cells written
298  */
299 BOOL WINAPI WriteConsoleOutputCharacterA( HANDLE hConsoleOutput, LPCSTR str, DWORD length,
300                                           COORD coord, LPDWORD lpNumCharsWritten )
301 {
302     BOOL ret;
303     LPWSTR strW;
304     DWORD lenW;
305
306     TRACE("(%d,%s,%ld,%dx%d,%p)\n", hConsoleOutput,
307           debugstr_an(str, length), length, coord.X, coord.Y, lpNumCharsWritten);
308
309     lenW = MultiByteToWideChar( GetConsoleOutputCP(), 0, str, length, NULL, 0 );
310
311     if (lpNumCharsWritten) *lpNumCharsWritten = 0;
312
313     if (!(strW = HeapAlloc( GetProcessHeap(), 0, lenW * sizeof(WCHAR) ))) return FALSE;
314     MultiByteToWideChar( GetConsoleOutputCP(), 0, str, length, strW, lenW );
315
316     ret = WriteConsoleOutputCharacterW( hConsoleOutput, strW, lenW, coord, lpNumCharsWritten );
317     HeapFree( GetProcessHeap(), 0, strW );
318     return ret;
319 }
320
321
322 /******************************************************************************
323  * WriteConsoleOutputAttribute [KERNEL32.@]  Sets attributes for some cells in
324  *                                           the console screen buffer
325  *
326  * PARAMS
327  *    hConsoleOutput    [I] Handle to screen buffer
328  *    attr              [I] Pointer to buffer with write attributes
329  *    length            [I] Number of cells to write to
330  *    coord             [I] Coords of first cell
331  *    lpNumAttrsWritten [O] Pointer to number of cells written
332  *
333  * RETURNS
334  *    Success: TRUE
335  *    Failure: FALSE
336  * 
337  */
338 BOOL WINAPI WriteConsoleOutputAttribute( HANDLE hConsoleOutput, CONST WORD *attr, DWORD length,
339                                          COORD coord, LPDWORD lpNumAttrsWritten )
340 {
341     BOOL ret;
342
343     TRACE("(%d,%p,%ld,%dx%d,%p)\n", hConsoleOutput,attr,length,coord.X,coord.Y,lpNumAttrsWritten);
344
345     SERVER_START_REQ( write_console_output )
346     {
347         req->handle = hConsoleOutput;
348         req->x      = coord.X;
349         req->y      = coord.Y;
350         req->mode   = CHAR_INFO_MODE_ATTR;
351         req->wrap   = TRUE;
352         wine_server_add_data( req, attr, length * sizeof(WORD) );
353         if ((ret = !wine_server_call_err( req )))
354         {
355             if (lpNumAttrsWritten) *lpNumAttrsWritten = reply->written;
356         }
357     }
358     SERVER_END_REQ;
359     return ret;
360 }
361
362
363 /******************************************************************************
364  * FillConsoleOutputCharacterA [KERNEL32.@]
365  *
366  * PARAMS
367  *    hConsoleOutput    [I] Handle to screen buffer
368  *    ch                [I] Character to write
369  *    length            [I] Number of cells to write to
370  *    coord             [I] Coords of first cell
371  *    lpNumCharsWritten [O] Pointer to number of cells written
372  *
373  * RETURNS
374  *    Success: TRUE
375  *    Failure: FALSE
376  */
377 BOOL WINAPI FillConsoleOutputCharacterA( HANDLE hConsoleOutput, CHAR ch, DWORD length,
378                                          COORD coord, LPDWORD lpNumCharsWritten )
379 {
380     WCHAR wch;
381
382     MultiByteToWideChar( GetConsoleOutputCP(), 0, &ch, 1, &wch, 1 );
383     return FillConsoleOutputCharacterW(hConsoleOutput, wch, length, coord, lpNumCharsWritten);
384 }
385
386
387 /******************************************************************************
388  * FillConsoleOutputCharacterW [KERNEL32.@]  Writes characters to console
389  *
390  * PARAMS
391  *    hConsoleOutput    [I] Handle to screen buffer
392  *    ch                [I] Character to write
393  *    length            [I] Number of cells to write to
394  *    coord             [I] Coords of first cell
395  *    lpNumCharsWritten [O] Pointer to number of cells written
396  *
397  * RETURNS
398  *    Success: TRUE
399  *    Failure: FALSE
400  */
401 BOOL WINAPI FillConsoleOutputCharacterW( HANDLE hConsoleOutput, WCHAR ch, DWORD length,
402                                          COORD coord, LPDWORD lpNumCharsWritten)
403 {
404     BOOL ret;
405
406     TRACE("(%d,%s,%ld,(%dx%d),%p)\n",
407           hConsoleOutput, debugstr_wn(&ch, 1), length, coord.X, coord.Y, lpNumCharsWritten);
408
409     SERVER_START_REQ( fill_console_output )
410     {
411         req->handle  = hConsoleOutput;
412         req->x       = coord.X;
413         req->y       = coord.Y;
414         req->mode    = CHAR_INFO_MODE_TEXT;
415         req->wrap    = TRUE;
416         req->data.ch = ch;
417         req->count   = length;
418         if ((ret = !wine_server_call_err( req )))
419         {
420             if (lpNumCharsWritten) *lpNumCharsWritten = reply->written;
421         }
422     }
423     SERVER_END_REQ;
424     return ret;
425 }
426
427
428 /******************************************************************************
429  * FillConsoleOutputAttribute [KERNEL32.@]  Sets attributes for console
430  *
431  * PARAMS
432  *    hConsoleOutput    [I] Handle to screen buffer
433  *    attr              [I] Color attribute to write
434  *    length            [I] Number of cells to write to
435  *    coord             [I] Coords of first cell
436  *    lpNumAttrsWritten [O] Pointer to number of cells written
437  *
438  * RETURNS
439  *    Success: TRUE
440  *    Failure: FALSE
441  */
442 BOOL WINAPI FillConsoleOutputAttribute( HANDLE hConsoleOutput, WORD attr, DWORD length,
443                                         COORD coord, LPDWORD lpNumAttrsWritten )
444 {
445     BOOL ret;
446
447     TRACE("(%d,%d,%ld,(%dx%d),%p)\n",
448           hConsoleOutput, attr, length, coord.X, coord.Y, lpNumAttrsWritten);
449
450     SERVER_START_REQ( fill_console_output )
451     {
452         req->handle    = hConsoleOutput;
453         req->x         = coord.X;
454         req->y         = coord.Y;
455         req->mode      = CHAR_INFO_MODE_ATTR;
456         req->wrap      = TRUE;
457         req->data.attr = attr;
458         req->count     = length;
459         if ((ret = !wine_server_call_err( req )))
460         {
461             if (lpNumAttrsWritten) *lpNumAttrsWritten = reply->written;
462         }
463     }
464     SERVER_END_REQ;
465     return ret;
466 }
467
468
469 /******************************************************************************
470  * ReadConsoleOutputCharacterA [KERNEL32.@]
471  * 
472  */
473 BOOL WINAPI ReadConsoleOutputCharacterA(HANDLE hConsoleOutput, LPSTR lpstr, DWORD count,
474                                         COORD coord, LPDWORD read_count)
475 {
476     DWORD read;
477     BOOL ret;
478     LPWSTR wptr = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR));
479
480     if (read_count) *read_count = 0;
481     if (!wptr) return FALSE;
482
483     if ((ret = ReadConsoleOutputCharacterW( hConsoleOutput, wptr, count, coord, &read )))
484     {
485         read = WideCharToMultiByte( GetConsoleOutputCP(), 0, wptr, read, lpstr, count, NULL, NULL);
486         if (read_count) *read_count = read;
487     }
488     HeapFree( GetProcessHeap(), 0, wptr );
489     return ret;
490 }
491
492
493 /******************************************************************************
494  * ReadConsoleOutputCharacterW [KERNEL32.@]
495  * 
496  */
497 BOOL WINAPI ReadConsoleOutputCharacterW( HANDLE hConsoleOutput, LPWSTR buffer, DWORD count,
498                                          COORD coord, LPDWORD read_count )
499 {
500     BOOL ret;
501
502     TRACE( "(%d,%p,%ld,%dx%d,%p)\n", hConsoleOutput, buffer, count, coord.X, coord.Y, read_count );
503
504     SERVER_START_REQ( read_console_output )
505     {
506         req->handle = hConsoleOutput;
507         req->x      = coord.X;
508         req->y      = coord.Y;
509         req->mode   = CHAR_INFO_MODE_TEXT;
510         req->wrap   = TRUE;
511         wine_server_set_reply( req, buffer, count * sizeof(WCHAR) );
512         if ((ret = !wine_server_call_err( req )))
513         {
514             if (read_count) *read_count = wine_server_reply_size(reply) / sizeof(WCHAR);
515         }
516     }
517     SERVER_END_REQ;
518     return ret;
519 }
520
521
522 /******************************************************************************
523  *  ReadConsoleOutputAttribute [KERNEL32.@]
524  */
525 BOOL WINAPI ReadConsoleOutputAttribute(HANDLE hConsoleOutput, LPWORD lpAttribute, DWORD length,
526                                        COORD coord, LPDWORD read_count)
527 {
528     BOOL ret;
529
530     TRACE("(%d,%p,%ld,%dx%d,%p)\n",
531           hConsoleOutput, lpAttribute, length, coord.X, coord.Y, read_count);
532
533     SERVER_START_REQ( read_console_output )
534     {
535         req->handle = hConsoleOutput;
536         req->x      = coord.X;
537         req->y      = coord.Y;
538         req->mode   = CHAR_INFO_MODE_ATTR;
539         req->wrap   = TRUE;
540         wine_server_set_reply( req, lpAttribute, length * sizeof(WORD) );
541         if ((ret = !wine_server_call_err( req )))
542         {
543             if (read_count) *read_count = wine_server_reply_size(reply) / sizeof(WORD);
544         }
545     }
546     SERVER_END_REQ;
547     return ret;
548 }
549
550
551 /******************************************************************************
552  *  ReadConsoleOutputA [KERNEL32.@]
553  * 
554  */
555 BOOL WINAPI ReadConsoleOutputA( HANDLE hConsoleOutput, LPCHAR_INFO lpBuffer, COORD size,
556                                 COORD coord, LPSMALL_RECT region )
557 {
558     BOOL ret;
559     int y;
560
561     ret = ReadConsoleOutputW( hConsoleOutput, lpBuffer, size, coord, region );
562     if (ret && region->Right >= region->Left)
563     {
564         for (y = 0; y <= region->Bottom - region->Top; y++)
565         {
566             char_info_WtoA( &lpBuffer[(coord.Y + y) * size.X + coord.X],
567                             region->Right - region->Left + 1 );
568         }
569     }
570     return ret;
571 }
572
573
574 /******************************************************************************
575  *  ReadConsoleOutputW [KERNEL32.@]
576  * 
577  * NOTE: The NT4 (sp5) kernel crashes on me if size is (0,0). I don't
578  * think we need to be *that* compatible.  -- AJ
579  */
580 BOOL WINAPI ReadConsoleOutputW( HANDLE hConsoleOutput, LPCHAR_INFO lpBuffer, COORD size,
581                                 COORD coord, LPSMALL_RECT region )
582 {
583     int width, height, y;
584     BOOL ret = TRUE;
585
586     width = min( region->Right - region->Left + 1, size.X - coord.X );
587     height = min( region->Bottom - region->Top + 1, size.Y - coord.Y );
588
589     if (width > 0 && height > 0)
590     {
591         for (y = 0; y < height; y++)
592         {
593             SERVER_START_REQ( read_console_output )
594             {
595                 req->handle = hConsoleOutput;
596                 req->x      = region->Left;
597                 req->y      = region->Top + y;
598                 req->mode   = CHAR_INFO_MODE_TEXTATTR;
599                 req->wrap   = FALSE;
600                 wine_server_set_reply( req, &lpBuffer[(y+coord.Y) * size.X + coord.X],
601                                        width * sizeof(CHAR_INFO) );
602                 if ((ret = !wine_server_call_err( req )))
603                 {
604                     width  = min( width, reply->width - region->Left );
605                     height = min( height, reply->height - region->Top );
606                 }
607             }
608             SERVER_END_REQ;
609             if (!ret) break;
610         }
611     }
612     region->Bottom = region->Top + height - 1;
613     region->Right = region->Left + width - 1;
614     return ret;
615 }
616
617
618 /******************************************************************************
619  * ReadConsoleInputA [KERNEL32.@]  Reads data from a console
620  *
621  * PARAMS
622  *    handle   [I] Handle to console input buffer
623  *    buffer   [O] Address of buffer for read data
624  *    count    [I] Number of records to read
625  *    pRead    [O] Address of number of records read
626  *
627  * RETURNS
628  *    Success: TRUE
629  *    Failure: FALSE
630  */
631 BOOL WINAPI ReadConsoleInputA( HANDLE handle, LPINPUT_RECORD buffer, DWORD count, LPDWORD pRead )
632 {
633     DWORD read;
634
635     if (!ReadConsoleInputW( handle, buffer, count, &read )) return FALSE;
636     input_records_WtoA( buffer, read );
637     if (pRead) *pRead = read;
638     return TRUE;
639 }
640
641
642 /***********************************************************************
643  *            PeekConsoleInputA   (KERNEL32.@)
644  *
645  * Gets 'count' first events (or less) from input queue.
646  */
647 BOOL WINAPI PeekConsoleInputA( HANDLE handle, LPINPUT_RECORD buffer, DWORD count, LPDWORD pRead )
648 {
649     DWORD read;
650
651     if (!PeekConsoleInputW( handle, buffer, count, &read )) return FALSE;
652     input_records_WtoA( buffer, read );
653     if (pRead) *pRead = read;
654     return TRUE;
655 }
656
657
658 /***********************************************************************
659  *            PeekConsoleInputW   (KERNEL32.@)
660  */
661 BOOL WINAPI PeekConsoleInputW( HANDLE handle, LPINPUT_RECORD buffer, DWORD count, LPDWORD read )
662 {
663     BOOL ret;
664     SERVER_START_REQ( read_console_input )
665     {
666         req->handle = handle;
667         req->flush  = FALSE;
668         wine_server_set_reply( req, buffer, count * sizeof(INPUT_RECORD) );
669         if ((ret = !wine_server_call_err( req )))
670         {
671             if (read) *read = count ? reply->read : 0;
672         }
673     }
674     SERVER_END_REQ;
675     return ret;
676 }
677
678
679 /***********************************************************************
680  *            GetNumberOfConsoleInputEvents   (KERNEL32.@)
681  */
682 BOOL WINAPI GetNumberOfConsoleInputEvents( HANDLE handle, LPDWORD nrofevents )
683 {
684     BOOL ret;
685     SERVER_START_REQ( read_console_input )
686     {
687         req->handle = handle;
688         req->flush  = FALSE;
689         if ((ret = !wine_server_call_err( req )))
690         {
691             if (nrofevents) *nrofevents = reply->read;
692         }
693     }
694     SERVER_END_REQ;
695     return ret;
696 }
697
698
699 /***********************************************************************
700  *            FlushConsoleInputBuffer   (KERNEL32.@)
701  */
702 BOOL WINAPI FlushConsoleInputBuffer( HANDLE handle )
703 {
704     BOOL ret;
705     SERVER_START_REQ( read_console_input )
706     {
707         req->handle = handle;
708         req->flush  = TRUE;
709         ret = !wine_server_call_err( req );
710     }
711     SERVER_END_REQ;
712     return ret;
713 }
714
715
716 /***********************************************************************
717  *            SetConsoleTitleA   (KERNEL32.@)
718  */
719 BOOL WINAPI SetConsoleTitleA( LPCSTR title )
720 {
721     LPWSTR titleW;
722     BOOL ret;
723
724     DWORD len = MultiByteToWideChar( GetConsoleOutputCP(), 0, title, -1, NULL, 0 );
725     if (!(titleW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)))) return FALSE;
726     MultiByteToWideChar( GetConsoleOutputCP(), 0, title, -1, titleW, len );
727     ret = SetConsoleTitleW(titleW);
728     HeapFree(GetProcessHeap(), 0, titleW);
729     return ret;
730 }
731
732
733 /***********************************************************************
734  *            GetConsoleTitleA   (KERNEL32.@)
735  */
736 DWORD WINAPI GetConsoleTitleA(LPSTR title, DWORD size)
737 {
738     WCHAR *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * size);
739     DWORD ret;
740
741     if (!ptr) return 0;
742     ret = GetConsoleTitleW( ptr, size );
743     if (ret)
744     {
745         WideCharToMultiByte( GetConsoleOutputCP(), 0, ptr, ret + 1, title, size, NULL, NULL);
746         ret = strlen(title);
747     }
748     return ret;
749 }
750
751
752 /******************************************************************************
753  * GetConsoleTitleW [KERNEL32.@]  Retrieves title string for console
754  *
755  * PARAMS
756  *    title [O] Address of buffer for title
757  *    size  [I] Size of buffer
758  *
759  * RETURNS
760  *    Success: Length of string copied
761  *    Failure: 0
762  */
763 DWORD WINAPI GetConsoleTitleW(LPWSTR title, DWORD size)
764 {
765     DWORD ret = 0;
766
767     SERVER_START_REQ( get_console_input_info )
768     {
769         req->handle = 0;
770         wine_server_set_reply( req, title, (size-1) * sizeof(WCHAR) );
771         if (!wine_server_call_err( req ))
772         {
773             ret = wine_server_reply_size(reply) / sizeof(WCHAR);
774             title[ret] = 0;
775         }
776     }
777     SERVER_END_REQ;
778     return ret;
779 }
780
781
782 /***********************************************************************
783  *            GetLargestConsoleWindowSize   (KERNEL32.@)
784  *
785  * NOTE
786  *      This should return a COORD, but calling convention for returning
787  *      structures is different between Windows and gcc on i386.
788  *
789  * VERSION: [i386]
790  */
791 #ifdef __i386__
792 #undef GetLargestConsoleWindowSize
793 DWORD WINAPI GetLargestConsoleWindowSize(HANDLE hConsoleOutput)
794 {
795     COORD c;
796     c.X = 80;
797     c.Y = 24;
798     return *(DWORD *)&c;
799 }
800 #endif /* defined(__i386__) */
801
802
803 /***********************************************************************
804  *            GetLargestConsoleWindowSize   (KERNEL32.@)
805  *
806  * NOTE
807  *      This should return a COORD, but calling convention for returning
808  *      structures is different between Windows and gcc on i386.
809  *
810  * VERSION: [!i386]
811  */
812 #ifndef __i386__
813 COORD WINAPI GetLargestConsoleWindowSize(HANDLE hConsoleOutput)
814 {
815     COORD c;
816     c.X = 80;
817     c.Y = 24;
818     return c;
819 }
820 #endif /* defined(__i386__) */