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