2 * Win32 kernel functions
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
12 /* Reference applications:
13 * - IDA (interactive disassembler) full version 3.75. Works.
14 * - LYNX/W32. Works mostly, some keys crash it.
28 #include "wine/server.h"
29 #include "wine/exception.h"
30 #include "wine/unicode.h"
31 #include "debugtools.h"
33 DEFAULT_DEBUG_CHANNEL(console);
36 static UINT console_input_codepage;
37 static UINT console_output_codepage;
39 /* map input records to ASCII */
40 static void input_records_WtoA( INPUT_RECORD *buffer, int count )
45 for (i = 0; i < count; i++)
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;
54 /* map input records to Unicode */
55 static void input_records_AtoW( INPUT_RECORD *buffer, int count )
60 for (i = 0; i < count; i++)
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;
69 /* map char infos to ASCII */
70 static void char_info_WtoA( CHAR_INFO *buffer, int count )
76 WideCharToMultiByte( GetConsoleOutputCP(), 0, &buffer->Char.UnicodeChar, 1,
78 buffer->Char.AsciiChar = ch;
83 /* map char infos to Unicode */
84 static void char_info_AtoW( CHAR_INFO *buffer, int count )
90 MultiByteToWideChar( GetConsoleOutputCP(), 0, &buffer->Char.AsciiChar, 1, &ch, 1 );
91 buffer->Char.UnicodeChar = ch;
97 /******************************************************************************
98 * GetConsoleCP [KERNEL32.@] Returns the OEM code page for the console
103 UINT WINAPI GetConsoleCP(VOID)
105 if (!console_input_codepage) console_input_codepage = GetOEMCP();
106 return console_input_codepage;
110 /******************************************************************************
111 * SetConsoleCP [KERNEL32.@]
113 BOOL WINAPI SetConsoleCP(UINT cp)
115 if (!IsValidCodePage( cp )) return FALSE;
116 console_input_codepage = cp;
121 /***********************************************************************
122 * GetConsoleOutputCP (KERNEL32.@)
124 UINT WINAPI GetConsoleOutputCP(VOID)
126 if (!console_output_codepage) console_output_codepage = GetOEMCP();
127 return console_output_codepage;
131 /******************************************************************************
132 * SetConsoleOutputCP [KERNEL32.@] Set the output codepage used by the console
135 * cp [I] code page to set
141 BOOL WINAPI SetConsoleOutputCP(UINT cp)
143 if (!IsValidCodePage( cp )) return FALSE;
144 console_output_codepage = cp;
149 /******************************************************************************
150 * WriteConsoleInputA [KERNEL32.@]
152 BOOL WINAPI WriteConsoleInputA( HANDLE handle, const INPUT_RECORD *buffer,
153 DWORD count, LPDWORD written )
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 );
167 /******************************************************************************
168 * WriteConsoleInputW [KERNEL32.@]
170 BOOL WINAPI WriteConsoleInputW( HANDLE handle, const INPUT_RECORD *buffer,
171 DWORD count, LPDWORD written )
175 TRACE("(%d,%p,%ld,%p)\n", handle, buffer, count, written);
177 if (written) *written = 0;
178 SERVER_START_REQ( write_console_input )
180 req->handle = handle;
181 wine_server_add_data( req, buffer, count * sizeof(INPUT_RECORD) );
182 if ((ret = !wine_server_call_err( req )))
184 if (written) *written = reply->written;
192 /***********************************************************************
193 * WriteConsoleOutputA (KERNEL32.@)
195 BOOL WINAPI WriteConsoleOutputA( HANDLE hConsoleOutput, const CHAR_INFO *lpBuffer,
196 COORD size, COORD coord, LPSMALL_RECT region )
200 COORD new_size, new_coord;
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 );
206 if (new_size.X <= 0 || new_size.Y <= 0)
208 region->Bottom = region->Top + new_size.Y - 1;
209 region->Right = region->Left + new_size.X - 1;
213 /* only copy the useful rectangle */
214 if (!(ciw = HeapAlloc( GetProcessHeap(), 0, sizeof(CHAR_INFO) * new_size.X * new_size.Y )))
216 for (y = 0; y < new_size.Y; y++)
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 );
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 );
229 /***********************************************************************
230 * WriteConsoleOutputW (KERNEL32.@)
232 BOOL WINAPI WriteConsoleOutputW( HANDLE hConsoleOutput, const CHAR_INFO *lpBuffer,
233 COORD size, COORD coord, LPSMALL_RECT region )
235 int width, height, y;
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);
242 width = min( region->Right - region->Left + 1, size.X - coord.X );
243 height = min( region->Bottom - region->Top + 1, size.Y - coord.Y );
245 if (width > 0 && height > 0)
247 for (y = 0; y < height; y++)
249 SERVER_START_REQ( write_console_output )
251 req->handle = hConsoleOutput;
252 req->x = region->Left;
253 req->y = region->Top + y;
254 req->mode = CHAR_INFO_MODE_TEXTATTR;
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 )))
260 width = min( width, reply->width - region->Left );
261 height = min( height, reply->height - region->Top );
268 region->Bottom = region->Top + height - 1;
269 region->Right = region->Left + width - 1;
274 /******************************************************************************
275 * WriteConsoleOutputCharacterA [KERNEL32.@] Copies character to consecutive
276 * cells in the console screen buffer
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
285 BOOL WINAPI WriteConsoleOutputCharacterA( HANDLE hConsoleOutput, LPCSTR str, DWORD length,
286 COORD coord, LPDWORD lpNumCharsWritten )
292 TRACE("(%d,%s,%ld,%dx%d,%p)\n", hConsoleOutput,
293 debugstr_an(str, length), length, coord.X, coord.Y, lpNumCharsWritten);
295 lenW = MultiByteToWideChar( GetConsoleOutputCP(), 0, str, length, NULL, 0 );
297 if (lpNumCharsWritten) *lpNumCharsWritten = 0;
299 if (!(strW = HeapAlloc( GetProcessHeap(), 0, lenW * sizeof(WCHAR) ))) return FALSE;
300 MultiByteToWideChar( GetConsoleOutputCP(), 0, str, length, strW, lenW );
302 ret = WriteConsoleOutputCharacterW( hConsoleOutput, strW, lenW, coord, lpNumCharsWritten );
303 HeapFree( GetProcessHeap(), 0, strW );
308 /******************************************************************************
309 * WriteConsoleOutputAttribute [KERNEL32.@] Sets attributes for some cells in
310 * the console screen buffer
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
324 BOOL WINAPI WriteConsoleOutputAttribute( HANDLE hConsoleOutput, CONST WORD *attr, DWORD length,
325 COORD coord, LPDWORD lpNumAttrsWritten )
329 TRACE("(%d,%p,%ld,%dx%d,%p)\n", hConsoleOutput,attr,length,coord.X,coord.Y,lpNumAttrsWritten);
331 SERVER_START_REQ( write_console_output )
333 req->handle = hConsoleOutput;
336 req->mode = CHAR_INFO_MODE_ATTR;
338 wine_server_add_data( req, attr, length * sizeof(WORD) );
339 if ((ret = !wine_server_call_err( req )))
341 if (lpNumAttrsWritten) *lpNumAttrsWritten = reply->written;
349 /******************************************************************************
350 * FillConsoleOutputCharacterA [KERNEL32.@]
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
363 BOOL WINAPI FillConsoleOutputCharacterA( HANDLE hConsoleOutput, CHAR ch, DWORD length,
364 COORD coord, LPDWORD lpNumCharsWritten )
368 MultiByteToWideChar( GetConsoleOutputCP(), 0, &ch, 1, &wch, 1 );
369 return FillConsoleOutputCharacterW(hConsoleOutput, wch, length, coord, lpNumCharsWritten);
373 /******************************************************************************
374 * FillConsoleOutputCharacterW [KERNEL32.@] Writes characters to console
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
387 BOOL WINAPI FillConsoleOutputCharacterW( HANDLE hConsoleOutput, WCHAR ch, DWORD length,
388 COORD coord, LPDWORD lpNumCharsWritten)
392 TRACE("(%d,%s,%ld,(%dx%d),%p)\n",
393 hConsoleOutput, debugstr_wn(&ch, 1), length, coord.X, coord.Y, lpNumCharsWritten);
395 SERVER_START_REQ( fill_console_output )
397 req->handle = hConsoleOutput;
400 req->mode = CHAR_INFO_MODE_TEXT;
404 if ((ret = !wine_server_call_err( req )))
406 if (lpNumCharsWritten) *lpNumCharsWritten = reply->written;
414 /******************************************************************************
415 * FillConsoleOutputAttribute [KERNEL32.@] Sets attributes for console
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
428 BOOL WINAPI FillConsoleOutputAttribute( HANDLE hConsoleOutput, WORD attr, DWORD length,
429 COORD coord, LPDWORD lpNumAttrsWritten )
433 TRACE("(%d,%d,%ld,(%dx%d),%p)\n",
434 hConsoleOutput, attr, length, coord.X, coord.Y, lpNumAttrsWritten);
436 SERVER_START_REQ( fill_console_output )
438 req->handle = hConsoleOutput;
441 req->mode = CHAR_INFO_MODE_ATTR;
443 req->data.attr = attr;
445 if ((ret = !wine_server_call_err( req )))
447 if (lpNumAttrsWritten) *lpNumAttrsWritten = reply->written;
455 /******************************************************************************
456 * ReadConsoleOutputCharacterA [KERNEL32.@]
459 BOOL WINAPI ReadConsoleOutputCharacterA(HANDLE hConsoleOutput, LPSTR lpstr, DWORD count,
460 COORD coord, LPDWORD read_count)
464 LPWSTR wptr = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR));
466 if (read_count) *read_count = 0;
467 if (!wptr) return FALSE;
469 if ((ret = ReadConsoleOutputCharacterW( hConsoleOutput, wptr, count, coord, &read )))
471 read = WideCharToMultiByte( GetConsoleOutputCP(), 0, wptr, read, lpstr, count, NULL, NULL);
472 if (read_count) *read_count = read;
474 HeapFree( GetProcessHeap(), 0, wptr );
479 /******************************************************************************
480 * ReadConsoleOutputCharacterW [KERNEL32.@]
483 BOOL WINAPI ReadConsoleOutputCharacterW( HANDLE hConsoleOutput, LPWSTR buffer, DWORD count,
484 COORD coord, LPDWORD read_count )
488 TRACE( "(%d,%p,%ld,%dx%d,%p)\n", hConsoleOutput, buffer, count, coord.X, coord.Y, read_count );
490 SERVER_START_REQ( read_console_output )
492 req->handle = hConsoleOutput;
495 req->mode = CHAR_INFO_MODE_TEXT;
497 wine_server_set_reply( req, buffer, count * sizeof(WCHAR) );
498 if ((ret = !wine_server_call_err( req )))
500 if (read_count) *read_count = wine_server_reply_size(reply) / sizeof(WCHAR);
508 /******************************************************************************
509 * ReadConsoleOutputAttribute [KERNEL32.@]
511 BOOL WINAPI ReadConsoleOutputAttribute(HANDLE hConsoleOutput, LPWORD lpAttribute, DWORD length,
512 COORD coord, LPDWORD read_count)
516 TRACE("(%d,%p,%ld,%dx%d,%p)\n",
517 hConsoleOutput, lpAttribute, length, coord.X, coord.Y, read_count);
519 SERVER_START_REQ( read_console_output )
521 req->handle = hConsoleOutput;
524 req->mode = CHAR_INFO_MODE_ATTR;
526 wine_server_set_reply( req, lpAttribute, length * sizeof(WORD) );
527 if ((ret = !wine_server_call_err( req )))
529 if (read_count) *read_count = wine_server_reply_size(reply) / sizeof(WORD);
537 /******************************************************************************
538 * ReadConsoleOutputA [KERNEL32.@]
541 BOOL WINAPI ReadConsoleOutputA( HANDLE hConsoleOutput, LPCHAR_INFO lpBuffer, COORD size,
542 COORD coord, LPSMALL_RECT region )
547 ret = ReadConsoleOutputW( hConsoleOutput, lpBuffer, size, coord, region );
548 if (ret && region->Right >= region->Left)
550 for (y = 0; y <= region->Bottom - region->Top; y++)
552 char_info_WtoA( &lpBuffer[(coord.Y + y) * size.X + coord.X],
553 region->Right - region->Left + 1 );
560 /******************************************************************************
561 * ReadConsoleOutputW [KERNEL32.@]
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
566 BOOL WINAPI ReadConsoleOutputW( HANDLE hConsoleOutput, LPCHAR_INFO lpBuffer, COORD size,
567 COORD coord, LPSMALL_RECT region )
569 int width, height, y;
572 width = min( region->Right - region->Left + 1, size.X - coord.X );
573 height = min( region->Bottom - region->Top + 1, size.Y - coord.Y );
575 if (width > 0 && height > 0)
577 for (y = 0; y < height; y++)
579 SERVER_START_REQ( read_console_output )
581 req->handle = hConsoleOutput;
582 req->x = region->Left;
583 req->y = region->Top + y;
584 req->mode = CHAR_INFO_MODE_TEXTATTR;
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 )))
590 width = min( width, reply->width - region->Left );
591 height = min( height, reply->height - region->Top );
598 region->Bottom = region->Top + height - 1;
599 region->Right = region->Left + width - 1;
604 /******************************************************************************
605 * ReadConsoleInputA [KERNEL32.@] Reads data from a console
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
617 BOOL WINAPI ReadConsoleInputA( HANDLE handle, LPINPUT_RECORD buffer, DWORD count, LPDWORD pRead )
621 if (!ReadConsoleInputW( handle, buffer, count, &read )) return FALSE;
622 input_records_WtoA( buffer, read );
623 if (pRead) *pRead = read;
628 /***********************************************************************
629 * PeekConsoleInputA (KERNEL32.@)
631 * Gets 'count' first events (or less) from input queue.
633 BOOL WINAPI PeekConsoleInputA( HANDLE handle, LPINPUT_RECORD buffer, DWORD count, LPDWORD pRead )
637 if (!PeekConsoleInputW( handle, buffer, count, &read )) return FALSE;
638 input_records_WtoA( buffer, read );
639 if (pRead) *pRead = read;
644 /***********************************************************************
645 * PeekConsoleInputW (KERNEL32.@)
647 BOOL WINAPI PeekConsoleInputW( HANDLE handle, LPINPUT_RECORD buffer, DWORD count, LPDWORD read )
650 SERVER_START_REQ( read_console_input )
652 req->handle = handle;
654 wine_server_set_reply( req, buffer, count * sizeof(INPUT_RECORD) );
655 if ((ret = !wine_server_call_err( req )))
657 if (read) *read = count ? reply->read : 0;
665 /***********************************************************************
666 * GetNumberOfConsoleInputEvents (KERNEL32.@)
668 BOOL WINAPI GetNumberOfConsoleInputEvents( HANDLE handle, LPDWORD nrofevents )
671 SERVER_START_REQ( read_console_input )
673 req->handle = handle;
675 if ((ret = !wine_server_call_err( req )))
677 if (nrofevents) *nrofevents = reply->read;
685 /***********************************************************************
686 * FlushConsoleInputBuffer (KERNEL32.@)
688 BOOL WINAPI FlushConsoleInputBuffer( HANDLE handle )
691 SERVER_START_REQ( read_console_input )
693 req->handle = handle;
695 ret = !wine_server_call_err( req );
702 /***********************************************************************
703 * SetConsoleTitleA (KERNEL32.@)
705 BOOL WINAPI SetConsoleTitleA( LPCSTR title )
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);
719 /***********************************************************************
720 * GetConsoleTitleA (KERNEL32.@)
722 DWORD WINAPI GetConsoleTitleA(LPSTR title, DWORD size)
724 WCHAR *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * size);
728 ret = GetConsoleTitleW( ptr, size );
731 WideCharToMultiByte( GetConsoleOutputCP(), 0, ptr, ret + 1, title, size, NULL, NULL);
738 /******************************************************************************
739 * GetConsoleTitleW [KERNEL32.@] Retrieves title string for console
742 * title [O] Address of buffer for title
743 * size [I] Size of buffer
746 * Success: Length of string copied
749 DWORD WINAPI GetConsoleTitleW(LPWSTR title, DWORD size)
753 SERVER_START_REQ( get_console_input_info )
756 wine_server_set_reply( req, title, (size-1) * sizeof(WCHAR) );
757 if (!wine_server_call_err( req ))
759 ret = wine_server_reply_size(reply) / sizeof(WCHAR);
768 /***********************************************************************
769 * GetLargestConsoleWindowSize (KERNEL32.@)
772 * This should return a COORD, but calling convention for returning
773 * structures is different between Windows and gcc on i386.
778 #undef GetLargestConsoleWindowSize
779 DWORD WINAPI GetLargestConsoleWindowSize(HANDLE hConsoleOutput)
786 #endif /* defined(__i386__) */
789 /***********************************************************************
790 * GetLargestConsoleWindowSize (KERNEL32.@)
793 * This should return a COORD, but calling convention for returning
794 * structures is different between Windows and gcc on i386.
799 COORD WINAPI GetLargestConsoleWindowSize(HANDLE hConsoleOutput)
806 #endif /* defined(__i386__) */