Release 980329
[wine] / win32 / 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  */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <termios.h>
13 #include <sys/ioctl.h>
14 #include <sys/types.h>
15 #include <unistd.h>
16 #include <fcntl.h>
17 #include <errno.h>
18 #include <signal.h>
19 #include <assert.h>
20 #include "windows.h"
21 #include "k32obj.h"
22 #include "file.h"
23 #include "process.h"
24 #include "winerror.h"
25 #include "wincon.h"
26 #include "heap.h"
27 #include "debug.h"
28
29 static CONSOLE_SCREEN_BUFFER_INFO dummyinfo =
30 {
31     {80, 24},
32     {0, 0},
33     0,
34     {0, 0, 79, 23},
35     {80, 24}
36 };
37
38 /* The console -- I chose to keep the master and slave
39  * (UNIX) file descriptors around in case they are needed for
40  * ioctls later.  The pid is needed to destroy the xterm on close
41  */
42 typedef struct _CONSOLE {
43         K32OBJ  header;
44         int     master;                 /* xterm side of pty */
45         int     slave;                  /* wine side of pty */
46         int     pid;                    /* xterm's pid, -1 if no xterm */
47         LPSTR   title;                  /* title of console */
48 } CONSOLE;
49
50
51 static void CONSOLE_Destroy( K32OBJ *obj );
52 static BOOL32 CONSOLE_Write(K32OBJ *ptr, LPCVOID lpBuffer, 
53                             DWORD nNumberOfChars,  LPDWORD lpNumberOfChars, 
54                             LPOVERLAPPED lpOverlapped);
55 static BOOL32 CONSOLE_Read(K32OBJ *ptr, LPVOID lpBuffer, 
56                            DWORD nNumberOfChars, LPDWORD lpNumberOfChars, 
57                            LPOVERLAPPED lpOverlapped);
58 static int wine_openpty(int *master, int *slave, char *name, 
59                      struct termios *term, struct winsize *winsize);
60 static BOOL32 wine_createConsole(int *master, int *slave, int *pid);
61
62 const K32OBJ_OPS CONSOLE_Ops =
63 {
64         NULL,                   /* signaled */
65         NULL,                   /* satisfied */
66         NULL,                   /* add_wait */
67         NULL,                   /* remove_wait */
68         CONSOLE_Read,           /* read */
69         CONSOLE_Write,          /* write */
70         CONSOLE_Destroy         /* destroy */
71 };
72
73
74
75
76 static void CONSOLE_Destroy(K32OBJ *obj)
77 {
78         CONSOLE *console = (CONSOLE *)obj;
79         assert(obj->type == K32OBJ_CONSOLE);
80
81         obj->type = K32OBJ_UNKNOWN;
82
83         if (console->title)
84                   HeapFree( SystemHeap, 0, console->title );
85         console->title = NULL;
86         /* make sure a xterm exists to kill */
87         if (console->pid != -1) {
88                 kill(console->pid, SIGTERM);
89         }
90         HeapFree(SystemHeap, 0, console);
91 }
92
93
94 /* lpOverlapped is ignored */
95 static BOOL32 CONSOLE_Read(K32OBJ *ptr, LPVOID lpBuffer, DWORD nNumberOfChars,
96                         LPDWORD lpNumberOfChars, LPOVERLAPPED lpOverlapped)
97 {
98         CONSOLE *console = (CONSOLE *)ptr;
99         int result;
100
101         TRACE(console, "%p %p %ld\n", ptr, lpBuffer,
102                      nNumberOfChars);
103
104         *lpNumberOfChars = 0; 
105
106         if ((result = read(console->slave, lpBuffer, nNumberOfChars)) == -1) {
107                 FILE_SetDosError();
108                 return FALSE;
109         }
110         *lpNumberOfChars = result;
111         return TRUE;
112 }
113
114
115 /* lpOverlapped is ignored */
116 static BOOL32 CONSOLE_Write(K32OBJ *ptr, LPCVOID lpBuffer, 
117                             DWORD nNumberOfChars,
118                             LPDWORD lpNumberOfChars, LPOVERLAPPED lpOverlapped)
119 {
120         CONSOLE *console = (CONSOLE *)ptr;
121         int result;
122
123         TRACE(console, "%p %p %ld\n", ptr, lpBuffer,
124                      nNumberOfChars);
125
126         *lpNumberOfChars = 0; 
127
128         /* 
129          * I assume this loop around EAGAIN is here because
130          * win32 doesn't have interrupted system calls 
131          */
132
133         for (;;)
134         {
135                 result = write(console->slave, lpBuffer, nNumberOfChars);
136                 if (result != -1) {
137                         *lpNumberOfChars = result;
138                         return TRUE;
139                 }
140                 if (errno != EINTR) {
141                         FILE_SetDosError();
142                         return FALSE;
143                 }
144         }
145 }
146
147
148
149
150 /***********************************************************************
151  *           SetConsoleCtrlHandler               (KERNEL32.459)
152  */
153 BOOL32 WINAPI SetConsoleCtrlHandler(HANDLER_ROUTINE * func,  BOOL32 a)
154 {
155         return 0;
156 }
157
158 /***********************************************************************
159  *           CreateConsoleScreenBuffer   (KERNEL32.151)
160  */
161 HANDLE32 WINAPI CreateConsoleScreenBuffer( DWORD dwDesiredAccess,
162                                            DWORD dwShareMode,
163                                            LPSECURITY_ATTRIBUTES lpSecurityAttributes,
164                                            DWORD dwFlags,
165                                            LPVOID lpScreenBufferData)
166 {
167         FIXME(console, "(...): stub !\n");
168         return INVALID_HANDLE_VALUE32;
169 }
170
171 /***********************************************************************
172  *           GetConsoleScreenBufferInfo   (KERNEL32.190)
173  */
174 BOOL32 WINAPI GetConsoleScreenBufferInfo( HANDLE32 hConsoleOutput,
175                                           LPCONSOLE_SCREEN_BUFFER_INFO csbi )
176 {
177     csbi->dwSize.x = 80;
178     csbi->dwSize.y = 24;
179     csbi->dwCursorPosition.x = 0;
180     csbi->dwCursorPosition.y = 0;
181     csbi->wAttributes = 0;
182     csbi->srWindow.Left = 0;
183     csbi->srWindow.Right        = 79;
184     csbi->srWindow.Top  = 0;
185     csbi->srWindow.Bottom       = 23;
186     csbi->dwMaximumWindowSize.x = 80;
187     csbi->dwMaximumWindowSize.y = 24;
188     return TRUE;
189 }
190
191 /***********************************************************************
192  *           SetConsoleActiveScreenBuffer   (KERNEL32.623)
193  */
194 BOOL32 WINAPI SetConsoleActiveScreenBuffer(HANDLE32 hConsoleOutput)
195 {
196         FIXME(console, "(%x): stub!\n", hConsoleOutput);
197         return 0;
198 }
199
200 /***********************************************************************
201  *            GetLargestConsoleWindowSize   (KERNEL32.226)
202  */
203 DWORD WINAPI GetLargestConsoleWindowSize( HANDLE32 hConsoleOutput )
204 {
205     return (DWORD)MAKELONG(dummyinfo.dwMaximumWindowSize.x,dummyinfo.dwMaximumWindowSize.y);
206 }
207
208 /***********************************************************************
209  *            FreeConsole (KERNEL32.267)
210  */
211 BOOL32 WINAPI FreeConsole(VOID)
212 {
213
214         PDB32 *pdb = PROCESS_Current();
215         CONSOLE *console;
216
217         SYSTEM_LOCK();
218
219         console = (CONSOLE *)pdb->console;
220
221         if (console == NULL) {
222                 SetLastError(ERROR_INVALID_PARAMETER);
223                 return FALSE;
224         }
225
226         PROCESS_CloseObjHandles(pdb, &console->header);
227
228         K32OBJ_DecCount( &console->header );
229         pdb->console = NULL;
230         SYSTEM_UNLOCK();
231         return TRUE;
232 }
233
234
235 /** 
236  *  It looks like the openpty that comes with glibc in RedHat 5.0
237  *  is buggy (second call returns what looks like a dup of 0 and 1
238  *  instead of a new pty), this is a generic replacement.
239  */
240 static int wine_openpty(int *master, int *slave, char *name, 
241                         struct termios *term, struct winsize *winsize)
242 {
243         int fdm, fds;
244         char *ptr1, *ptr2;
245         char pts_name[512];
246
247         strcpy (pts_name, "/dev/ptyXY");
248
249         for (ptr1 = "pqrstuvwxyzPQRST"; *ptr1 != 0; ptr1++) {
250                 pts_name[8] = *ptr1;
251                 for (ptr2 = "0123456789abcdef"; *ptr2 != 0; ptr2++) {
252                         pts_name[9] = *ptr2;
253
254                         if ((fdm = open(pts_name, O_RDWR)) < 0) {
255                                 if (errno == ENOENT)
256                                         return -1;
257                                 else
258                                         continue;
259                         }
260                         pts_name[5] = 't';
261                         if ((fds = open(pts_name, O_RDWR)) < 0) {
262                                 pts_name[5] = 'p';
263                                 continue;
264                         }
265                         *master = fdm;
266                         *slave = fds;
267                         
268                         if (term != NULL)
269                                 tcsetattr(*slave, TCSANOW, term);
270                         if (winsize != NULL)
271                                 ioctl(*slave, TIOCSWINSZ, winsize);
272                         if (name != NULL)
273                                 strcpy(name, pts_name);
274                         return fds;
275                 }
276         }
277         return -1;
278 }
279
280 static BOOL32 wine_createConsole(int *master, int *slave, int *pid)
281 {
282         struct termios term;
283         char buf[1024];
284         char c = '\0';
285         int status = 0;
286         int i;
287
288         if (tcgetattr(0, &term) < 0) return FALSE;
289         term.c_lflag |= ICANON;
290         term.c_lflag &= ~ECHO;
291         if (wine_openpty(master, slave, NULL, &term, NULL) < 0) return FALSE;
292
293         if ((*pid=fork()) == 0) {
294                 tcsetattr(*slave, TCSADRAIN, &term);
295                 sprintf(buf, "-Sxx%d", *master);
296                 execlp("xterm", "xterm", buf, NULL);
297                 ERR(console, "error creating AllocConsole xterm\n");
298                 exit(1);
299         }
300
301         /* most xterms like to print their window ID when used with -S;
302          * read it and continue before the user has a chance...
303          * NOTE: this is the reason we started xterm with ECHO off, 
304          * we'll turn it back on below
305          */
306
307         for (i=0; c!='\n'; (status=read(*slave, &c, 1)), i++) {
308                 if (status == -1 && c == '\0') {
309                                 /* wait for xterm to be created */
310                         usleep(100);
311                 }
312                 if (i > 10000) {
313                         WARN(console, "can't read xterm WID\n");
314                         kill(*pid, SIGKILL);
315                         return FALSE;
316                 }
317         }
318         term.c_lflag |= ECHO;
319         tcsetattr(*master, TCSADRAIN, &term);
320
321         return TRUE;
322
323 }
324
325 /***********************************************************************
326  *              CONSOLE_GetConsoleHandle
327  *       returns a 16-bit style console handle
328  * note: only called from _lopen
329  */
330 HFILE32 CONSOLE_GetConsoleHandle(VOID)
331 {
332         PDB32 *pdb = PROCESS_Current();
333         HFILE32 handle = HFILE_ERROR32;
334
335         SYSTEM_LOCK();
336         if (pdb->console != NULL) {
337                 CONSOLE *console = (CONSOLE *)pdb->console;
338                 handle = (HFILE32)HANDLE_Alloc(&console->header, 0, TRUE);
339         }
340         SYSTEM_UNLOCK();
341         return handle;
342 }
343
344 /***********************************************************************
345  *            AllocConsole (KERNEL32.103)
346  *
347  * creates an xterm with a pty to our program
348  */
349 BOOL32 WINAPI AllocConsole(VOID)
350 {
351
352         int master;
353         int slave;
354         int pid;
355         PDB32 *pdb = PROCESS_Current();
356         CONSOLE *console;
357         HANDLE32 hIn, hOut, hErr;
358
359         SYSTEM_LOCK();          /* FIXME: really only need to lock the process */
360
361         SetLastError(ERROR_CANNOT_MAKE);  /* this might not be the right 
362                                              error, but it's a good guess :) */
363
364         console = (CONSOLE *)pdb->console;
365
366         /* don't create a console if we already have one */
367         if (console != NULL) {
368                 SetLastError(ERROR_ACCESS_DENIED);
369                 SYSTEM_UNLOCK();
370                 return FALSE;
371         }
372
373         if (!(console = (CONSOLE*)HeapAlloc( SystemHeap, 0, sizeof(*console))))
374         {
375             SYSTEM_UNLOCK();
376             return FALSE;
377         }
378
379         console->header.type     = K32OBJ_CONSOLE;
380         console->header.refcount = 1;
381         console->pid             = -1;
382         console->title           = NULL;
383
384         if (wine_createConsole(&master, &slave, &pid) == FALSE) {
385                 K32OBJ_DecCount(&console->header);
386                 SYSTEM_UNLOCK();
387                 return FALSE;
388         }
389
390         /* save the pid and other info for future use */
391         console->master = master;
392         console->slave = slave;
393         console->pid = pid;
394
395         if ((hIn = HANDLE_Alloc(&console->header, 0, TRUE)) == INVALID_HANDLE_VALUE32)
396         {
397             K32OBJ_DecCount(&console->header);
398             SYSTEM_UNLOCK();
399             return FALSE;
400         }
401
402         if ((hOut = HANDLE_Alloc(&console->header, 0, TRUE)) == INVALID_HANDLE_VALUE32)
403         {
404             CloseHandle(hIn);
405             K32OBJ_DecCount(&console->header);
406             SYSTEM_UNLOCK();
407             return FALSE;
408         }
409
410
411         if ((hErr = HANDLE_Alloc(&console->header, 0, TRUE)) == INVALID_HANDLE_VALUE32)
412         {
413             CloseHandle(hIn);
414             CloseHandle(hOut);
415             K32OBJ_DecCount(&console->header);
416             SYSTEM_UNLOCK();
417             return FALSE;
418         }
419
420         /* associate this console with the process */
421         if (pdb->console) K32OBJ_DecCount( pdb->console );
422         pdb->console = (K32OBJ *)console;
423
424         /* NT resets the STD_*_HANDLEs on console alloc */
425         SetStdHandle(STD_INPUT_HANDLE, hIn);
426         SetStdHandle(STD_OUTPUT_HANDLE, hOut);
427         SetStdHandle(STD_ERROR_HANDLE, hErr);
428
429         SetLastError(ERROR_SUCCESS);
430         SYSTEM_UNLOCK();
431         SetConsoleTitle32A("Wine Console");
432         return TRUE;
433 }
434
435
436 /***********************************************************************
437  *            GetConsoleCP   (KERNEL32.226)
438  */
439 UINT32 WINAPI GetConsoleCP(VOID)
440 {
441     return GetACP();
442 }
443
444 /***********************************************************************
445  *            GetConsoleOutputCP   (KERNEL32.189)
446  */
447 UINT32 WINAPI GetConsoleOutputCP(VOID)
448 {
449     return GetConsoleCP();
450 }
451
452 /***********************************************************************
453  *            GetConsoleMode   (KERNEL32.188)
454  */
455 BOOL32 WINAPI GetConsoleMode(HANDLE32 hcon,LPDWORD mode)
456 {
457         *mode =         ENABLE_PROCESSED_INPUT  |
458                         ENABLE_LINE_INPUT       |
459                         ENABLE_ECHO_INPUT;
460         return TRUE;
461 }
462
463 /***********************************************************************
464  *            SetConsoleMode   (KERNEL32.628)
465  */
466 BOOL32 WINAPI SetConsoleMode(HANDLE32 hcon,DWORD mode)
467 {
468         FIXME(console,"(%08x,%08lx): stub\n",hcon,mode);
469         return TRUE;
470 }
471
472 /***********************************************************************
473  *            GetConsoleTitleA   (KERNEL32.191)
474  */
475 DWORD WINAPI GetConsoleTitle32A(LPSTR title,DWORD size)
476 {
477         PDB32 *pdb = PROCESS_Current();
478         CONSOLE *console= (CONSOLE *)pdb->console;
479
480         if(console && console->title) 
481           {
482             lstrcpyn32A(title,console->title,size);
483             return strlen(title);
484           }
485         return 0;
486 }
487
488 /***********************************************************************
489  *            GetConsoleTitleW   (KERNEL32.192)
490  */
491 DWORD WINAPI GetConsoleTitle32W(LPWSTR title,DWORD size)
492 {
493         PDB32 *pdb = PROCESS_Current();
494         CONSOLE *console= (CONSOLE *)pdb->console;
495         if(console && console->title) 
496           {
497             lstrcpynAtoW(title,console->title,size);
498             return (lstrlen32W(title));
499           }
500         return 0;
501 }
502
503 /***********************************************************************
504  *            WriteConsoleA   (KERNEL32.729)
505  */
506 BOOL32 WINAPI WriteConsole32A( HANDLE32 hConsoleOutput,
507                                LPCVOID lpBuffer,
508                                DWORD nNumberOfCharsToWrite,
509                                LPDWORD lpNumberOfCharsWritten,
510                                LPVOID lpReserved )
511 {
512         /* FIXME: should I check if this is a console handle? */
513         return WriteFile(hConsoleOutput, lpBuffer, nNumberOfCharsToWrite,
514                          lpNumberOfCharsWritten, NULL);
515 }
516
517 /***********************************************************************
518  *            WriteConsoleOutputA   (KERNEL32.732)
519  */
520 BOOL32 WINAPI WriteConsoleOutput32A( HANDLE32 hConsoleOutput,
521                                      LPCHAR_INFO lpBuffer,
522                                      COORD dwBufferSize,
523                                      COORD dwBufferCoord,
524                                      LPSMALL_RECT lpWriteRegion)
525 {
526         return FALSE;
527 }
528
529 /***********************************************************************
530  *            WriteConsoleW   (KERNEL32.577)
531  */
532 BOOL32 WINAPI WriteConsole32W( HANDLE32 hConsoleOutput,
533                                LPCVOID lpBuffer,
534                                DWORD nNumberOfCharsToWrite,
535                                LPDWORD lpNumberOfCharsWritten,
536                                LPVOID lpReserved )
537 {
538         BOOL32 ret;
539         LPSTR xstring=HeapAlloc( GetProcessHeap(), 0, nNumberOfCharsToWrite );
540
541         lstrcpynWtoA( xstring,  lpBuffer,nNumberOfCharsToWrite);
542
543         /* FIXME: should I check if this is a console handle? */
544         ret= WriteFile(hConsoleOutput, xstring, nNumberOfCharsToWrite,
545                          lpNumberOfCharsWritten, NULL);
546         HeapFree( GetProcessHeap(), 0, xstring );
547         return ret;
548
549 }
550
551 /***********************************************************************
552  *            ReadConsoleA   (KERNEL32.419)
553  */
554 BOOL32 WINAPI ReadConsole32A( HANDLE32 hConsoleInput,
555                               LPVOID lpBuffer,
556                               DWORD nNumberOfCharsToRead,
557                               LPDWORD lpNumberOfCharsRead,
558                               LPVOID lpReserved )
559 {
560         return ReadFile(hConsoleInput, lpBuffer, nNumberOfCharsToRead,
561                         lpNumberOfCharsRead, NULL);
562
563 #ifdef OLD
564         fgets(lpBuffer,nNumberOfCharsToRead, CONSOLE_console.conIO);
565         if (ferror(CONSOLE_console.conIO) {
566                 clearerr();
567                 return FALSE;
568         }
569         *lpNumberOfCharsRead = strlen(lpBuffer);
570         return TRUE;
571 #endif
572
573 }
574
575 /***********************************************************************
576  *            ReadConsoleW   (KERNEL32.427)
577  */
578 BOOL32 WINAPI ReadConsole32W( HANDLE32 hConsoleInput,
579                               LPVOID lpBuffer,
580                               DWORD nNumberOfCharsToRead,
581                               LPDWORD lpNumberOfCharsRead,
582                               LPVOID lpReserved )
583 {
584         BOOL32 ret;
585         LPSTR buf = (LPSTR)HeapAlloc(GetProcessHeap(), 0, 
586                                        nNumberOfCharsToRead);
587         ret = ReadFile(hConsoleInput, buf, nNumberOfCharsToRead,
588                         lpNumberOfCharsRead, NULL);
589         lstrcpynAtoW(lpBuffer,buf,nNumberOfCharsToRead);
590         *lpNumberOfCharsRead = strlen(buf);
591         HeapFree( GetProcessHeap(), 0, buf );
592         return ret;
593
594 #ifdef OLD
595         LPSTR buf = (LPSTR)HEAP_xalloc(GetProcessHeap(), 0, 
596                                        nNumberOfCharsToRead);
597         fgets(buf, nNumberOfCharsToRead, CONSOLE_console.conIO);
598
599         if (ferror(CONSOLE_console.conIO) {
600                 HeapFree( GetProcessHeap(), 0, buf );
601                 clearerr();
602                 return FALSE;
603         }
604
605         lstrcpynAtoW(lpBuffer,buf,nNumberOfCharsToRead);
606         *lpNumberOfCharsRead = strlen(buf);
607         HeapFree( GetProcessHeap(), 0, buf );
608         return TRUE;
609 #endif
610
611 }
612
613 /***********************************************************************
614  *            SetConsoleTitle32A   (KERNEL32.476)
615  */
616 BOOL32 WINAPI SetConsoleTitle32A(LPCSTR title)
617 {
618         PDB32 *pdb = PROCESS_Current();
619         CONSOLE *console;
620         DWORD written;
621         char titleformat[]="\033]2;%s\a"; /*this should work for xterms*/
622         LPSTR titlestring; 
623         BOOL32 ret=FALSE;
624
625         TRACE(console,"SetConsoleTitle(%s)\n",title);
626         
627         console = (CONSOLE *)pdb->console;
628         if (!console)
629           return FALSE;
630         if(console->title) /* Free old title, if there is one */
631           HeapFree( SystemHeap, 0, console->title );
632         console->title = (LPSTR)HeapAlloc(SystemHeap, 0,strlen(title)+1);
633         if(console->title) strcpy(console->title,title);
634
635         titlestring = HeapAlloc(GetProcessHeap(), 0,strlen(title)+strlen(titleformat)+1);
636         if (!titlestring)
637           return FALSE;
638         
639         sprintf(titlestring,titleformat,title);
640         /* Ugly casting */
641         CONSOLE_Write((K32OBJ *)console,titlestring,strlen(titlestring),&written,NULL);
642         if (written == strlen(titlestring))
643           ret =TRUE;
644         HeapFree( GetProcessHeap(), 0, titlestring );
645         return ret;
646 }
647
648 /***********************************************************************
649  *            SetConsoleTitle32W   (KERNEL32.477)
650  */
651 BOOL32 WINAPI SetConsoleTitle32W( LPCWSTR title )
652 {
653     BOOL32 ret;
654
655     LPSTR titleA = HEAP_strdupWtoA( GetProcessHeap(), 0, title );
656     ret = SetConsoleTitle32A(titleA);
657     HeapFree( GetProcessHeap(), 0, titleA );
658     return ret;
659 }
660
661 /***********************************************************************
662  *            FlushConsoleInputBuffer   (KERNEL32.132)
663  */
664 BOOL32 WINAPI FlushConsoleInputBuffer(HANDLE32 hConsoleInput)
665 {
666     FIXME(console,"(%d): stub\n",hConsoleInput);
667     return TRUE;
668 }
669
670 BOOL32 WINAPI SetConsoleCursorPosition(HANDLE32 hcons,COORD c)
671 {
672     /* x are columns, y rows */
673     if (!c.y) {
674         fprintf(stderr,"\r");
675         if (c.x)
676                 fprintf(stderr,"%c[%dC", 0x1B, c.x); /* note: 0x1b == ESC */
677         return TRUE;
678     }
679     /* handle rest of the cases */
680     return FALSE;
681 }
682
683 /***********************************************************************
684  *            GetNumberOfConsoleInputEvents   (KERNEL32.246)
685  */
686 BOOL32 WINAPI GetNumberOfConsoleInputEvents(HANDLE32 hcon,LPDWORD nrofevents)
687 {
688         *nrofevents = 0;
689         return TRUE;
690 }
691
692 /***********************************************************************
693  *            GetNumberOfConsoleMouseButtons   (KERNEL32.358)
694  */
695 BOOL32 WINAPI GetNumberOfConsoleMouseButtons(LPDWORD nrofbuttons)
696 {
697     *nrofbuttons = 2;
698     FIXME(console,"(%p): STUB returning 2\n", nrofbuttons);
699     return TRUE;
700 }
701
702 /***********************************************************************
703  *            PeekConsoleInputA   (KERNEL32.550)
704  */
705 BOOL32 WINAPI PeekConsoleInput32A(HANDLE32 hConsoleInput,
706                                   LPINPUT_RECORD pirBuffer,
707                                   DWORD cInRecords,
708                                   LPDWORD lpcRead)
709 {
710     pirBuffer = NULL;
711     cInRecords = 0;
712     *lpcRead = 0;
713     FIXME(console,"(...): STUB returning TRUE\n");
714         return TRUE;
715 }
716
717 /***********************************************************************
718  *            PeekConsoleInputW   (KERNEL32.551)
719  */
720 BOOL32 WINAPI PeekConsoleInput32W(HANDLE32 hConsoleInput,
721                                   LPINPUT_RECORD pirBuffer,
722                                   DWORD cInRecords,
723                                   LPDWORD lpcRead)
724 {
725     pirBuffer = NULL;
726     cInRecords = 0;
727     *lpcRead = 0;
728     FIXME(console,"(...): STUB returning TRUE\n");
729     return TRUE;
730 }
731
732 /***********************************************************************
733  *            GetConsoleCursorInfo32   (KERNEL32.296)
734  */
735 BOOL32 WINAPI GetConsoleCursorInfo32(HANDLE32 hcon, LPDWORD cinfo)
736 {
737   cinfo[0] = 10; /* 10% of character box is cursor.  */
738   cinfo[1] = TRUE;  /* Cursor is visible.  */
739   FIXME(console, "(%x,%p): STUB!\n", hcon, cinfo);
740   return TRUE;
741 }
742
743 /***********************************************************************
744  *            SetConsoleCursorInfo32   (KERNEL32.626)
745  */
746 BOOL32 WINAPI SetConsoleCursorInfo32(HANDLE32 hcon, LPDWORD cinfo)
747 {
748   FIXME(console, "(%#x,%p): STUB!\n", hcon, cinfo);
749   return TRUE;
750 }
751
752 /***********************************************************************
753  *            SetConsoleWindowInfo32   (KERNEL32.634)
754  */
755 BOOL32 WINAPI SetConsoleWindowInfo32(HANDLE32 hcon, BOOL32 flag, LPSMALL_RECT window)
756 {
757   FIXME(console, "(%x,%d,%p): STUB!\n", hcon, flag, window);
758   return TRUE;
759 }
760
761 /***********************************************************************
762  *               (KERNEL32.631)
763  */
764 BOOL32 WINAPI SetConsoleTextAttribute32(HANDLE32 hcon, DWORD attributes)
765 {
766   FIXME(console, "(%#x,%#lx): STUB!\n", hcon, attributes);
767   return TRUE;
768 }
769