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
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.
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.
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
26 /* Reference applications:
27 * - IDA (interactive disassembler) full version 3.75. Works.
28 * - LYNX/W32. Works mostly, some keys crash it.
42 #include "wine/server.h"
43 #include "wine/exception.h"
44 #include "wine/unicode.h"
45 #include "wine/debug.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(console
);
50 static UINT console_input_codepage
;
51 static UINT console_output_codepage
;
53 /* map input records to ASCII */
54 static void input_records_WtoA( INPUT_RECORD
*buffer
, int count
)
59 for (i
= 0; i
< count
; i
++)
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
;
68 /* map input records to Unicode */
69 static void input_records_AtoW( INPUT_RECORD
*buffer
, int count
)
74 for (i
= 0; i
< count
; i
++)
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
;
83 /* map char infos to ASCII */
84 static void char_info_WtoA( CHAR_INFO
*buffer
, int count
)
90 WideCharToMultiByte( GetConsoleOutputCP(), 0, &buffer
->Char
.UnicodeChar
, 1,
92 buffer
->Char
.AsciiChar
= ch
;
97 /* map char infos to Unicode */
98 static void char_info_AtoW( CHAR_INFO
*buffer
, int count
)
104 MultiByteToWideChar( GetConsoleOutputCP(), 0, &buffer
->Char
.AsciiChar
, 1, &ch
, 1 );
105 buffer
->Char
.UnicodeChar
= ch
;
111 /******************************************************************************
112 * GetConsoleCP [KERNEL32.@] Returns the OEM code page for the console
117 UINT WINAPI
GetConsoleCP(VOID
)
119 if (!console_input_codepage
) console_input_codepage
= GetOEMCP();
120 return console_input_codepage
;
124 /******************************************************************************
125 * SetConsoleCP [KERNEL32.@]
127 BOOL WINAPI
SetConsoleCP(UINT cp
)
129 if (!IsValidCodePage( cp
)) return FALSE
;
130 console_input_codepage
= cp
;
135 /***********************************************************************
136 * GetConsoleOutputCP (KERNEL32.@)
138 UINT WINAPI
GetConsoleOutputCP(VOID
)
140 if (!console_output_codepage
) console_output_codepage
= GetOEMCP();
141 return console_output_codepage
;
145 /******************************************************************************
146 * SetConsoleOutputCP [KERNEL32.@] Set the output codepage used by the console
149 * cp [I] code page to set
155 BOOL WINAPI
SetConsoleOutputCP(UINT cp
)
157 if (!IsValidCodePage( cp
)) return FALSE
;
158 console_output_codepage
= cp
;
163 /******************************************************************************
164 * WriteConsoleInputA [KERNEL32.@]
166 BOOL WINAPI
WriteConsoleInputA( HANDLE handle
, const INPUT_RECORD
*buffer
,
167 DWORD count
, LPDWORD written
)
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
);
181 /******************************************************************************
182 * WriteConsoleInputW [KERNEL32.@]
184 BOOL WINAPI
WriteConsoleInputW( HANDLE handle
, const INPUT_RECORD
*buffer
,
185 DWORD count
, LPDWORD written
)
189 TRACE("(%d,%p,%ld,%p)\n", handle
, buffer
, count
, written
);
191 if (written
) *written
= 0;
192 SERVER_START_REQ( write_console_input
)
194 req
->handle
= handle
;
195 wine_server_add_data( req
, buffer
, count
* sizeof(INPUT_RECORD
) );
196 if ((ret
= !wine_server_call_err( req
)))
198 if (written
) *written
= reply
->written
;
206 /***********************************************************************
207 * WriteConsoleOutputA (KERNEL32.@)
209 BOOL WINAPI
WriteConsoleOutputA( HANDLE hConsoleOutput
, const CHAR_INFO
*lpBuffer
,
210 COORD size
, COORD coord
, LPSMALL_RECT region
)
214 COORD new_size
, new_coord
;
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
);
220 if (new_size
.X
<= 0 || new_size
.Y
<= 0)
222 region
->Bottom
= region
->Top
+ new_size
.Y
- 1;
223 region
->Right
= region
->Left
+ new_size
.X
- 1;
227 /* only copy the useful rectangle */
228 if (!(ciw
= HeapAlloc( GetProcessHeap(), 0, sizeof(CHAR_INFO
) * new_size
.X
* new_size
.Y
)))
230 for (y
= 0; y
< new_size
.Y
; y
++)
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
);
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
);
243 /***********************************************************************
244 * WriteConsoleOutputW (KERNEL32.@)
246 BOOL WINAPI
WriteConsoleOutputW( HANDLE hConsoleOutput
, const CHAR_INFO
*lpBuffer
,
247 COORD size
, COORD coord
, LPSMALL_RECT region
)
249 int width
, height
, y
;
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
);
256 width
= min( region
->Right
- region
->Left
+ 1, size
.X
- coord
.X
);
257 height
= min( region
->Bottom
- region
->Top
+ 1, size
.Y
- coord
.Y
);
259 if (width
> 0 && height
> 0)
261 for (y
= 0; y
< height
; y
++)
263 SERVER_START_REQ( write_console_output
)
265 req
->handle
= hConsoleOutput
;
266 req
->x
= region
->Left
;
267 req
->y
= region
->Top
+ y
;
268 req
->mode
= CHAR_INFO_MODE_TEXTATTR
;
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
)))
274 width
= min( width
, reply
->width
- region
->Left
);
275 height
= min( height
, reply
->height
- region
->Top
);
282 region
->Bottom
= region
->Top
+ height
- 1;
283 region
->Right
= region
->Left
+ width
- 1;
288 /******************************************************************************
289 * WriteConsoleOutputCharacterA [KERNEL32.@] Copies character to consecutive
290 * cells in the console screen buffer
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
299 BOOL WINAPI
WriteConsoleOutputCharacterA( HANDLE hConsoleOutput
, LPCSTR str
, DWORD length
,
300 COORD coord
, LPDWORD lpNumCharsWritten
)
306 TRACE("(%d,%s,%ld,%dx%d,%p)\n", hConsoleOutput
,
307 debugstr_an(str
, length
), length
, coord
.X
, coord
.Y
, lpNumCharsWritten
);
309 lenW
= MultiByteToWideChar( GetConsoleOutputCP(), 0, str
, length
, NULL
, 0 );
311 if (lpNumCharsWritten
) *lpNumCharsWritten
= 0;
313 if (!(strW
= HeapAlloc( GetProcessHeap(), 0, lenW
* sizeof(WCHAR
) ))) return FALSE
;
314 MultiByteToWideChar( GetConsoleOutputCP(), 0, str
, length
, strW
, lenW
);
316 ret
= WriteConsoleOutputCharacterW( hConsoleOutput
, strW
, lenW
, coord
, lpNumCharsWritten
);
317 HeapFree( GetProcessHeap(), 0, strW
);
322 /******************************************************************************
323 * WriteConsoleOutputAttribute [KERNEL32.@] Sets attributes for some cells in
324 * the console screen buffer
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
338 BOOL WINAPI
WriteConsoleOutputAttribute( HANDLE hConsoleOutput
, CONST WORD
*attr
, DWORD length
,
339 COORD coord
, LPDWORD lpNumAttrsWritten
)
343 TRACE("(%d,%p,%ld,%dx%d,%p)\n", hConsoleOutput
,attr
,length
,coord
.X
,coord
.Y
,lpNumAttrsWritten
);
345 SERVER_START_REQ( write_console_output
)
347 req
->handle
= hConsoleOutput
;
350 req
->mode
= CHAR_INFO_MODE_ATTR
;
352 wine_server_add_data( req
, attr
, length
* sizeof(WORD
) );
353 if ((ret
= !wine_server_call_err( req
)))
355 if (lpNumAttrsWritten
) *lpNumAttrsWritten
= reply
->written
;
363 /******************************************************************************
364 * FillConsoleOutputCharacterA [KERNEL32.@]
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
377 BOOL WINAPI
FillConsoleOutputCharacterA( HANDLE hConsoleOutput
, CHAR ch
, DWORD length
,
378 COORD coord
, LPDWORD lpNumCharsWritten
)
382 MultiByteToWideChar( GetConsoleOutputCP(), 0, &ch
, 1, &wch
, 1 );
383 return FillConsoleOutputCharacterW(hConsoleOutput
, wch
, length
, coord
, lpNumCharsWritten
);
387 /******************************************************************************
388 * FillConsoleOutputCharacterW [KERNEL32.@] Writes characters to console
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
401 BOOL WINAPI
FillConsoleOutputCharacterW( HANDLE hConsoleOutput
, WCHAR ch
, DWORD length
,
402 COORD coord
, LPDWORD lpNumCharsWritten
)
406 TRACE("(%d,%s,%ld,(%dx%d),%p)\n",
407 hConsoleOutput
, debugstr_wn(&ch
, 1), length
, coord
.X
, coord
.Y
, lpNumCharsWritten
);
409 SERVER_START_REQ( fill_console_output
)
411 req
->handle
= hConsoleOutput
;
414 req
->mode
= CHAR_INFO_MODE_TEXT
;
418 if ((ret
= !wine_server_call_err( req
)))
420 if (lpNumCharsWritten
) *lpNumCharsWritten
= reply
->written
;
428 /******************************************************************************
429 * FillConsoleOutputAttribute [KERNEL32.@] Sets attributes for console
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
442 BOOL WINAPI
FillConsoleOutputAttribute( HANDLE hConsoleOutput
, WORD attr
, DWORD length
,
443 COORD coord
, LPDWORD lpNumAttrsWritten
)
447 TRACE("(%d,%d,%ld,(%dx%d),%p)\n",
448 hConsoleOutput
, attr
, length
, coord
.X
, coord
.Y
, lpNumAttrsWritten
);
450 SERVER_START_REQ( fill_console_output
)
452 req
->handle
= hConsoleOutput
;
455 req
->mode
= CHAR_INFO_MODE_ATTR
;
457 req
->data
.attr
= attr
;
459 if ((ret
= !wine_server_call_err( req
)))
461 if (lpNumAttrsWritten
) *lpNumAttrsWritten
= reply
->written
;
469 /******************************************************************************
470 * ReadConsoleOutputCharacterA [KERNEL32.@]
473 BOOL WINAPI
ReadConsoleOutputCharacterA(HANDLE hConsoleOutput
, LPSTR lpstr
, DWORD count
,
474 COORD coord
, LPDWORD read_count
)
478 LPWSTR wptr
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WCHAR
));
480 if (read_count
) *read_count
= 0;
481 if (!wptr
) return FALSE
;
483 if ((ret
= ReadConsoleOutputCharacterW( hConsoleOutput
, wptr
, count
, coord
, &read
)))
485 read
= WideCharToMultiByte( GetConsoleOutputCP(), 0, wptr
, read
, lpstr
, count
, NULL
, NULL
);
486 if (read_count
) *read_count
= read
;
488 HeapFree( GetProcessHeap(), 0, wptr
);
493 /******************************************************************************
494 * ReadConsoleOutputCharacterW [KERNEL32.@]
497 BOOL WINAPI
ReadConsoleOutputCharacterW( HANDLE hConsoleOutput
, LPWSTR buffer
, DWORD count
,
498 COORD coord
, LPDWORD read_count
)
502 TRACE( "(%d,%p,%ld,%dx%d,%p)\n", hConsoleOutput
, buffer
, count
, coord
.X
, coord
.Y
, read_count
);
504 SERVER_START_REQ( read_console_output
)
506 req
->handle
= hConsoleOutput
;
509 req
->mode
= CHAR_INFO_MODE_TEXT
;
511 wine_server_set_reply( req
, buffer
, count
* sizeof(WCHAR
) );
512 if ((ret
= !wine_server_call_err( req
)))
514 if (read_count
) *read_count
= wine_server_reply_size(reply
) / sizeof(WCHAR
);
522 /******************************************************************************
523 * ReadConsoleOutputAttribute [KERNEL32.@]
525 BOOL WINAPI
ReadConsoleOutputAttribute(HANDLE hConsoleOutput
, LPWORD lpAttribute
, DWORD length
,
526 COORD coord
, LPDWORD read_count
)
530 TRACE("(%d,%p,%ld,%dx%d,%p)\n",
531 hConsoleOutput
, lpAttribute
, length
, coord
.X
, coord
.Y
, read_count
);
533 SERVER_START_REQ( read_console_output
)
535 req
->handle
= hConsoleOutput
;
538 req
->mode
= CHAR_INFO_MODE_ATTR
;
540 wine_server_set_reply( req
, lpAttribute
, length
* sizeof(WORD
) );
541 if ((ret
= !wine_server_call_err( req
)))
543 if (read_count
) *read_count
= wine_server_reply_size(reply
) / sizeof(WORD
);
551 /******************************************************************************
552 * ReadConsoleOutputA [KERNEL32.@]
555 BOOL WINAPI
ReadConsoleOutputA( HANDLE hConsoleOutput
, LPCHAR_INFO lpBuffer
, COORD size
,
556 COORD coord
, LPSMALL_RECT region
)
561 ret
= ReadConsoleOutputW( hConsoleOutput
, lpBuffer
, size
, coord
, region
);
562 if (ret
&& region
->Right
>= region
->Left
)
564 for (y
= 0; y
<= region
->Bottom
- region
->Top
; y
++)
566 char_info_WtoA( &lpBuffer
[(coord
.Y
+ y
) * size
.X
+ coord
.X
],
567 region
->Right
- region
->Left
+ 1 );
574 /******************************************************************************
575 * ReadConsoleOutputW [KERNEL32.@]
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
580 BOOL WINAPI
ReadConsoleOutputW( HANDLE hConsoleOutput
, LPCHAR_INFO lpBuffer
, COORD size
,
581 COORD coord
, LPSMALL_RECT region
)
583 int width
, height
, y
;
586 width
= min( region
->Right
- region
->Left
+ 1, size
.X
- coord
.X
);
587 height
= min( region
->Bottom
- region
->Top
+ 1, size
.Y
- coord
.Y
);
589 if (width
> 0 && height
> 0)
591 for (y
= 0; y
< height
; y
++)
593 SERVER_START_REQ( read_console_output
)
595 req
->handle
= hConsoleOutput
;
596 req
->x
= region
->Left
;
597 req
->y
= region
->Top
+ y
;
598 req
->mode
= CHAR_INFO_MODE_TEXTATTR
;
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
)))
604 width
= min( width
, reply
->width
- region
->Left
);
605 height
= min( height
, reply
->height
- region
->Top
);
612 region
->Bottom
= region
->Top
+ height
- 1;
613 region
->Right
= region
->Left
+ width
- 1;
618 /******************************************************************************
619 * ReadConsoleInputA [KERNEL32.@] Reads data from a console
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
631 BOOL WINAPI
ReadConsoleInputA( HANDLE handle
, LPINPUT_RECORD buffer
, DWORD count
, LPDWORD pRead
)
635 if (!ReadConsoleInputW( handle
, buffer
, count
, &read
)) return FALSE
;
636 input_records_WtoA( buffer
, read
);
637 if (pRead
) *pRead
= read
;
642 /***********************************************************************
643 * PeekConsoleInputA (KERNEL32.@)
645 * Gets 'count' first events (or less) from input queue.
647 BOOL WINAPI
PeekConsoleInputA( HANDLE handle
, LPINPUT_RECORD buffer
, DWORD count
, LPDWORD pRead
)
651 if (!PeekConsoleInputW( handle
, buffer
, count
, &read
)) return FALSE
;
652 input_records_WtoA( buffer
, read
);
653 if (pRead
) *pRead
= read
;
658 /***********************************************************************
659 * PeekConsoleInputW (KERNEL32.@)
661 BOOL WINAPI
PeekConsoleInputW( HANDLE handle
, LPINPUT_RECORD buffer
, DWORD count
, LPDWORD read
)
664 SERVER_START_REQ( read_console_input
)
666 req
->handle
= handle
;
668 wine_server_set_reply( req
, buffer
, count
* sizeof(INPUT_RECORD
) );
669 if ((ret
= !wine_server_call_err( req
)))
671 if (read
) *read
= count
? reply
->read
: 0;
679 /***********************************************************************
680 * GetNumberOfConsoleInputEvents (KERNEL32.@)
682 BOOL WINAPI
GetNumberOfConsoleInputEvents( HANDLE handle
, LPDWORD nrofevents
)
685 SERVER_START_REQ( read_console_input
)
687 req
->handle
= handle
;
689 if ((ret
= !wine_server_call_err( req
)))
691 if (nrofevents
) *nrofevents
= reply
->read
;
699 /***********************************************************************
700 * FlushConsoleInputBuffer (KERNEL32.@)
702 BOOL WINAPI
FlushConsoleInputBuffer( HANDLE handle
)
705 SERVER_START_REQ( read_console_input
)
707 req
->handle
= handle
;
709 ret
= !wine_server_call_err( req
);
716 /***********************************************************************
717 * SetConsoleTitleA (KERNEL32.@)
719 BOOL WINAPI
SetConsoleTitleA( LPCSTR title
)
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
);
733 /***********************************************************************
734 * GetConsoleTitleA (KERNEL32.@)
736 DWORD WINAPI
GetConsoleTitleA(LPSTR title
, DWORD size
)
738 WCHAR
*ptr
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
) * size
);
742 ret
= GetConsoleTitleW( ptr
, size
);
745 WideCharToMultiByte( GetConsoleOutputCP(), 0, ptr
, ret
+ 1, title
, size
, NULL
, NULL
);
752 /******************************************************************************
753 * GetConsoleTitleW [KERNEL32.@] Retrieves title string for console
756 * title [O] Address of buffer for title
757 * size [I] Size of buffer
760 * Success: Length of string copied
763 DWORD WINAPI
GetConsoleTitleW(LPWSTR title
, DWORD size
)
767 SERVER_START_REQ( get_console_input_info
)
770 wine_server_set_reply( req
, title
, (size
-1) * sizeof(WCHAR
) );
771 if (!wine_server_call_err( req
))
773 ret
= wine_server_reply_size(reply
) / sizeof(WCHAR
);
782 /***********************************************************************
783 * GetLargestConsoleWindowSize (KERNEL32.@)
786 * This should return a COORD, but calling convention for returning
787 * structures is different between Windows and gcc on i386.
792 #undef GetLargestConsoleWindowSize
793 DWORD WINAPI
GetLargestConsoleWindowSize(HANDLE hConsoleOutput
)
800 #endif /* defined(__i386__) */
803 /***********************************************************************
804 * GetLargestConsoleWindowSize (KERNEL32.@)
807 * This should return a COORD, but calling convention for returning
808 * structures is different between Windows and gcc on i386.
813 COORD WINAPI
GetLargestConsoleWindowSize(HANDLE hConsoleOutput
)
820 #endif /* defined(__i386__) */