2 * Win32 console 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,2002,2004,2005,2010 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #define NONAMELESSUNION
33 #define WIN32_NO_STATUS
39 #include "wine/server.h"
40 #include "wine/exception.h"
41 #include "wine/debug.h"
42 #include "kernelbase.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(console
);
47 static CRITICAL_SECTION console_section
;
48 static CRITICAL_SECTION_DEBUG critsect_debug
=
50 0, 0, &console_section
,
51 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
52 0, 0, { (DWORD_PTR
)(__FILE__
": console_section") }
54 static CRITICAL_SECTION console_section
= { &critsect_debug
, -1, 0, 0, 0, 0 };
56 static WCHAR input_exe
[MAX_PATH
+ 1];
59 /* map a kernel32 console handle onto a real wineserver handle */
60 static inline obj_handle_t
console_handle_unmap( HANDLE h
)
62 return wine_server_obj_handle( console_handle_map( h
) );
65 /* map input records to ASCII */
66 static void input_records_WtoA( INPUT_RECORD
*buffer
, int count
)
68 UINT cp
= GetConsoleCP();
72 for (i
= 0; i
< count
; i
++)
74 if (buffer
[i
].EventType
!= KEY_EVENT
) continue;
75 WideCharToMultiByte( cp
, 0, &buffer
[i
].Event
.KeyEvent
.uChar
.UnicodeChar
, 1, &ch
, 1, NULL
, NULL
);
76 buffer
[i
].Event
.KeyEvent
.uChar
.AsciiChar
= ch
;
80 /* map input records to Unicode */
81 static void input_records_AtoW( INPUT_RECORD
*buffer
, int count
)
83 UINT cp
= GetConsoleCP();
87 for (i
= 0; i
< count
; i
++)
89 if (buffer
[i
].EventType
!= KEY_EVENT
) continue;
90 MultiByteToWideChar( cp
, 0, &buffer
[i
].Event
.KeyEvent
.uChar
.AsciiChar
, 1, &ch
, 1 );
91 buffer
[i
].Event
.KeyEvent
.uChar
.UnicodeChar
= ch
;
95 /* map char infos to ASCII */
96 static void char_info_WtoA( CHAR_INFO
*buffer
, int count
)
98 UINT cp
= GetConsoleOutputCP();
103 WideCharToMultiByte( cp
, 0, &buffer
->Char
.UnicodeChar
, 1, &ch
, 1, NULL
, NULL
);
104 buffer
->Char
.AsciiChar
= ch
;
109 /* map char infos to Unicode */
110 static void char_info_AtoW( CHAR_INFO
*buffer
, int count
)
112 UINT cp
= GetConsoleOutputCP();
117 MultiByteToWideChar( cp
, 0, &buffer
->Char
.AsciiChar
, 1, &ch
, 1 );
118 buffer
->Char
.UnicodeChar
= ch
;
123 /* helper function for ScrollConsoleScreenBufferW */
124 static void fill_console_output( HANDLE handle
, int i
, int j
, int len
, CHAR_INFO
*fill
)
126 SERVER_START_REQ( fill_console_output
)
128 req
->handle
= console_handle_unmap( handle
);
129 req
->mode
= CHAR_INFO_MODE_TEXTATTR
;
134 req
->data
.ch
= fill
->Char
.UnicodeChar
;
135 req
->data
.attr
= fill
->Attributes
;
136 wine_server_call_err( req
);
141 /* helper function for GetLargestConsoleWindowSize */
142 static COORD
get_largest_console_window_size( HANDLE handle
)
146 SERVER_START_REQ( get_console_output_info
)
148 req
->handle
= console_handle_unmap( handle
);
149 if (!wine_server_call_err( req
))
151 c
.X
= reply
->max_width
;
152 c
.Y
= reply
->max_height
;
156 TRACE( "(%p), returning %dx%d\n", handle
, c
.X
, c
.Y
);
160 /* helper function to replace OpenConsoleW */
161 HANDLE
open_console( BOOL output
, DWORD access
, SECURITY_ATTRIBUTES
*sa
, DWORD creation
)
165 if (creation
!= OPEN_EXISTING
)
167 SetLastError( ERROR_INVALID_PARAMETER
);
168 return INVALID_HANDLE_VALUE
;
171 SERVER_START_REQ( open_console
)
173 req
->from
= wine_server_obj_handle( ULongToHandle( output
));
174 req
->access
= access
;
175 req
->attributes
= sa
&& sa
->bInheritHandle
? OBJ_INHERIT
: 0;
176 req
->share
= FILE_SHARE_READ
| FILE_SHARE_WRITE
;
177 wine_server_call_err( req
);
178 ret
= wine_server_ptr_handle( reply
->handle
);
181 if (ret
) ret
= console_handle_map( ret
);
186 /******************************************************************
187 * AttachConsole (kernelbase.@)
189 BOOL WINAPI DECLSPEC_HOTPATCH
AttachConsole( DWORD pid
)
193 TRACE( "(%x)\n", pid
);
195 SERVER_START_REQ( attach_console
)
198 if ((ret
= !wine_server_call_err( req
)))
200 SetStdHandle( STD_INPUT_HANDLE
, wine_server_ptr_handle( reply
->std_in
));
201 SetStdHandle( STD_OUTPUT_HANDLE
, wine_server_ptr_handle( reply
->std_out
));
202 SetStdHandle( STD_ERROR_HANDLE
, wine_server_ptr_handle( reply
->std_err
));
210 /******************************************************************************
211 * CreateConsoleScreenBuffer (kernelbase.@)
213 HANDLE WINAPI DECLSPEC_HOTPATCH
CreateConsoleScreenBuffer( DWORD access
, DWORD share
,
214 SECURITY_ATTRIBUTES
*sa
, DWORD flags
,
217 HANDLE ret
= INVALID_HANDLE_VALUE
;
219 TRACE( "(%x,%x,%p,%x,%p)\n", access
, share
, sa
, flags
, data
);
221 if (flags
!= CONSOLE_TEXTMODE_BUFFER
|| data
)
223 SetLastError( ERROR_INVALID_PARAMETER
);
224 return INVALID_HANDLE_VALUE
;
227 SERVER_START_REQ( create_console_output
)
230 req
->access
= access
;
231 req
->attributes
= (sa
&& sa
->bInheritHandle
) ? OBJ_INHERIT
: 0;
234 if (!wine_server_call_err( req
))
235 ret
= console_handle_map( wine_server_ptr_handle( reply
->handle_out
));
242 /******************************************************************************
243 * FillConsoleOutputAttribute (kernelbase.@)
245 BOOL WINAPI DECLSPEC_HOTPATCH
FillConsoleOutputAttribute( HANDLE handle
, WORD attr
, DWORD length
,
246 COORD coord
, DWORD
*written
)
250 TRACE( "(%p,%d,%d,(%dx%d),%p)\n", handle
, attr
, length
, coord
.X
, coord
.Y
, written
);
254 SetLastError( ERROR_INVALID_ACCESS
);
259 SERVER_START_REQ( fill_console_output
)
261 req
->handle
= console_handle_unmap( handle
);
264 req
->mode
= CHAR_INFO_MODE_ATTR
;
266 req
->data
.attr
= attr
;
268 if ((ret
= !wine_server_call_err( req
))) *written
= reply
->written
;
275 /******************************************************************************
276 * FillConsoleOutputCharacterA (kernelbase.@)
278 BOOL WINAPI DECLSPEC_HOTPATCH
FillConsoleOutputCharacterA( HANDLE handle
, CHAR ch
, DWORD length
,
279 COORD coord
, DWORD
*written
)
283 MultiByteToWideChar( GetConsoleOutputCP(), 0, &ch
, 1, &wch
, 1 );
284 return FillConsoleOutputCharacterW( handle
, wch
, length
, coord
, written
);
288 /******************************************************************************
289 * FillConsoleOutputCharacterW (kernelbase.@)
291 BOOL WINAPI DECLSPEC_HOTPATCH
FillConsoleOutputCharacterW( HANDLE handle
, WCHAR ch
, DWORD length
,
292 COORD coord
, DWORD
*written
)
296 TRACE( "(%p,%s,%d,(%dx%d),%p)\n", handle
, debugstr_wn(&ch
, 1), length
, coord
.X
, coord
.Y
, written
);
300 SetLastError( ERROR_INVALID_ACCESS
);
305 SERVER_START_REQ( fill_console_output
)
307 req
->handle
= console_handle_unmap( handle
);
310 req
->mode
= CHAR_INFO_MODE_TEXT
;
314 if ((ret
= !wine_server_call_err( req
))) *written
= reply
->written
;
321 /***********************************************************************
322 * FreeConsole (kernelbase.@)
324 BOOL WINAPI DECLSPEC_HOTPATCH
FreeConsole(void)
328 SERVER_START_REQ( free_console
)
330 ret
= !wine_server_call_err( req
);
337 /******************************************************************************
338 * GenerateConsoleCtrlEvent (kernelbase.@)
340 BOOL WINAPI DECLSPEC_HOTPATCH
GenerateConsoleCtrlEvent( DWORD event
, DWORD group
)
344 TRACE( "(%d, %x)\n", event
, group
);
346 if (event
!= CTRL_C_EVENT
&& event
!= CTRL_BREAK_EVENT
)
348 ERR( "Invalid event %d for PGID %x\n", event
, group
);
352 SERVER_START_REQ( send_console_signal
)
355 req
->group_id
= group
;
356 ret
= !wine_server_call_err( req
);
363 /******************************************************************************
364 * GetConsoleCP (kernelbase.@)
366 UINT WINAPI DECLSPEC_HOTPATCH
GetConsoleCP(void)
368 UINT codepage
= GetOEMCP(); /* default value */
370 SERVER_START_REQ( get_console_input_info
)
373 if (!wine_server_call_err( req
))
375 if (reply
->input_cp
) codepage
= reply
->input_cp
;
383 /******************************************************************************
384 * GetConsoleCursorInfo (kernelbase.@)
386 BOOL WINAPI DECLSPEC_HOTPATCH
GetConsoleCursorInfo( HANDLE handle
, CONSOLE_CURSOR_INFO
*info
)
390 SERVER_START_REQ( get_console_output_info
)
392 req
->handle
= console_handle_unmap( handle
);
393 ret
= !wine_server_call_err( req
);
396 info
->dwSize
= reply
->cursor_size
;
397 info
->bVisible
= reply
->cursor_visible
;
402 if (!ret
) return FALSE
;
405 SetLastError( ERROR_INVALID_ACCESS
);
408 TRACE("(%p) returning (%d,%d)\n", handle
, info
->dwSize
, info
->bVisible
);
413 /***********************************************************************
414 * GetConsoleInputExeNameA (kernelbase.@)
416 BOOL WINAPI DECLSPEC_HOTPATCH
GetConsoleInputExeNameA( DWORD len
, LPSTR buffer
)
418 RtlEnterCriticalSection( &console_section
);
419 if (WideCharToMultiByte( CP_ACP
, 0, input_exe
, -1, NULL
, 0, NULL
, NULL
) <= len
)
420 WideCharToMultiByte( CP_ACP
, 0, input_exe
, -1, buffer
, len
, NULL
, NULL
);
421 else SetLastError(ERROR_BUFFER_OVERFLOW
);
422 RtlLeaveCriticalSection( &console_section
);
427 /***********************************************************************
428 * GetConsoleInputExeNameW (kernelbase.@)
430 BOOL WINAPI DECLSPEC_HOTPATCH
GetConsoleInputExeNameW( DWORD len
, LPWSTR buffer
)
432 RtlEnterCriticalSection( &console_section
);
433 if (len
> lstrlenW(input_exe
)) lstrcpyW( buffer
, input_exe
);
434 else SetLastError( ERROR_BUFFER_OVERFLOW
);
435 RtlLeaveCriticalSection( &console_section
);
440 /***********************************************************************
441 * GetConsoleMode (kernelbase.@)
443 BOOL WINAPI DECLSPEC_HOTPATCH
GetConsoleMode( HANDLE handle
, DWORD
*mode
)
447 SERVER_START_REQ( get_console_mode
)
449 req
->handle
= console_handle_unmap( handle
);
450 if ((ret
= !wine_server_call_err( req
)))
452 if (mode
) *mode
= reply
->mode
;
460 /***********************************************************************
461 * GetConsoleOutputCP (kernelbase.@)
463 UINT WINAPI DECLSPEC_HOTPATCH
GetConsoleOutputCP(void)
465 UINT codepage
= GetOEMCP(); /* default value */
467 SERVER_START_REQ( get_console_input_info
)
470 if (!wine_server_call_err( req
))
472 if (reply
->output_cp
) codepage
= reply
->output_cp
;
480 /***********************************************************************
481 * GetConsoleScreenBufferInfo (kernelbase.@)
483 BOOL WINAPI DECLSPEC_HOTPATCH
GetConsoleScreenBufferInfo( HANDLE handle
, CONSOLE_SCREEN_BUFFER_INFO
*info
)
487 SERVER_START_REQ( get_console_output_info
)
489 req
->handle
= console_handle_unmap( handle
);
490 if ((ret
= !wine_server_call_err( req
)))
492 info
->dwSize
.X
= reply
->width
;
493 info
->dwSize
.Y
= reply
->height
;
494 info
->dwCursorPosition
.X
= reply
->cursor_x
;
495 info
->dwCursorPosition
.Y
= reply
->cursor_y
;
496 info
->wAttributes
= reply
->attr
;
497 info
->srWindow
.Left
= reply
->win_left
;
498 info
->srWindow
.Right
= reply
->win_right
;
499 info
->srWindow
.Top
= reply
->win_top
;
500 info
->srWindow
.Bottom
= reply
->win_bottom
;
501 info
->dwMaximumWindowSize
.X
= min(reply
->width
, reply
->max_width
);
502 info
->dwMaximumWindowSize
.Y
= min(reply
->height
, reply
->max_height
);
507 TRACE( "(%p,(%d,%d) (%d,%d) %d (%d,%d-%d,%d) (%d,%d)\n", handle
,
508 info
->dwSize
.X
, info
->dwSize
.Y
, info
->dwCursorPosition
.X
, info
->dwCursorPosition
.Y
,
509 info
->wAttributes
, info
->srWindow
.Left
, info
->srWindow
.Top
, info
->srWindow
.Right
,
510 info
->srWindow
.Bottom
, info
->dwMaximumWindowSize
.X
, info
->dwMaximumWindowSize
.Y
);
515 /***********************************************************************
516 * GetConsoleScreenBufferInfoEx (kernelbase.@)
518 BOOL WINAPI DECLSPEC_HOTPATCH
GetConsoleScreenBufferInfoEx( HANDLE handle
,
519 CONSOLE_SCREEN_BUFFER_INFOEX
*info
)
523 if (info
->cbSize
!= sizeof(CONSOLE_SCREEN_BUFFER_INFOEX
))
525 SetLastError( ERROR_INVALID_PARAMETER
);
529 SERVER_START_REQ( get_console_output_info
)
531 req
->handle
= console_handle_unmap( handle
);
532 wine_server_set_reply( req
, info
->ColorTable
, sizeof(info
->ColorTable
) );
533 if ((ret
= !wine_server_call_err( req
)))
535 info
->dwSize
.X
= reply
->width
;
536 info
->dwSize
.Y
= reply
->height
;
537 info
->dwCursorPosition
.X
= reply
->cursor_x
;
538 info
->dwCursorPosition
.Y
= reply
->cursor_y
;
539 info
->wAttributes
= reply
->attr
;
540 info
->srWindow
.Left
= reply
->win_left
;
541 info
->srWindow
.Top
= reply
->win_top
;
542 info
->srWindow
.Right
= reply
->win_right
;
543 info
->srWindow
.Bottom
= reply
->win_bottom
;
544 info
->dwMaximumWindowSize
.X
= min( reply
->width
, reply
->max_width
);
545 info
->dwMaximumWindowSize
.Y
= min( reply
->height
, reply
->max_height
);
546 info
->wPopupAttributes
= reply
->popup_attr
;
547 info
->bFullscreenSupported
= FALSE
;
555 /******************************************************************************
556 * GetConsoleTitleW (kernelbase.@)
558 DWORD WINAPI DECLSPEC_HOTPATCH
GetConsoleTitleW( LPWSTR title
, DWORD size
)
562 SERVER_START_REQ( get_console_input_info
)
565 wine_server_set_reply( req
, title
, (size
- 1) * sizeof(WCHAR
) );
566 if (!wine_server_call_err( req
))
568 ret
= wine_server_reply_size(reply
) / sizeof(WCHAR
);
577 /***********************************************************************
578 * GetLargestConsoleWindowSize (kernelbase.@)
580 #if defined(__i386__) && !defined(__MINGW32__)
581 #undef GetLargestConsoleWindowSize
582 DWORD WINAPI DECLSPEC_HOTPATCH
GetLargestConsoleWindowSize( HANDLE handle
)
588 x
.c
= get_largest_console_window_size( handle
);
594 COORD WINAPI DECLSPEC_HOTPATCH
GetLargestConsoleWindowSize( HANDLE handle
)
596 return get_largest_console_window_size( handle
);
599 #endif /* !defined(__i386__) */
602 /***********************************************************************
603 * GetNumberOfConsoleInputEvents (kernelbase.@)
605 BOOL WINAPI DECLSPEC_HOTPATCH
GetNumberOfConsoleInputEvents( HANDLE handle
, DWORD
*count
)
609 SERVER_START_REQ( read_console_input
)
611 req
->handle
= console_handle_unmap( handle
);
613 if ((ret
= !wine_server_call_err( req
)))
615 if (count
) *count
= reply
->read
;
618 SetLastError( ERROR_INVALID_ACCESS
);
628 /***********************************************************************
629 * PeekConsoleInputA (kernelbase.@)
631 BOOL WINAPI DECLSPEC_HOTPATCH
PeekConsoleInputA( HANDLE handle
, INPUT_RECORD
*buffer
,
632 DWORD length
, DWORD
*count
)
636 if (!PeekConsoleInputW( handle
, buffer
, length
, &read
)) return FALSE
;
637 input_records_WtoA( buffer
, read
);
638 if (count
) *count
= read
;
643 /***********************************************************************
644 * PeekConsoleInputW (kernelbase.@)
646 BOOL WINAPI DECLSPEC_HOTPATCH
PeekConsoleInputW( HANDLE handle
, INPUT_RECORD
*buffer
,
647 DWORD length
, DWORD
*count
)
651 SERVER_START_REQ( read_console_input
)
653 req
->handle
= console_handle_unmap( handle
);
655 wine_server_set_reply( req
, buffer
, length
* sizeof(INPUT_RECORD
) );
656 if ((ret
= !wine_server_call_err( req
)))
658 if (count
) *count
= length
? reply
->read
: 0;
666 /******************************************************************************
667 * ReadConsoleOutputAttribute (kernelbase.@)
669 BOOL WINAPI DECLSPEC_HOTPATCH
ReadConsoleOutputAttribute( HANDLE handle
, WORD
*attr
, DWORD length
,
670 COORD coord
, DWORD
*count
)
674 TRACE( "(%p,%p,%d,%dx%d,%p)\n", handle
, attr
, length
, coord
.X
, coord
.Y
, count
);
678 SetLastError( ERROR_INVALID_ACCESS
);
683 SERVER_START_REQ( read_console_output
)
685 req
->handle
= console_handle_unmap( handle
);
688 req
->mode
= CHAR_INFO_MODE_ATTR
;
690 wine_server_set_reply( req
, attr
, length
* sizeof(WORD
) );
691 if ((ret
= !wine_server_call_err( req
))) *count
= wine_server_reply_size(reply
) / sizeof(WORD
);
698 /******************************************************************************
699 * ReadConsoleOutputCharacterA (kernelbase.@)
701 BOOL WINAPI DECLSPEC_HOTPATCH
ReadConsoleOutputCharacterA( HANDLE handle
, LPSTR buffer
, DWORD length
,
702 COORD coord
, DWORD
*count
)
710 SetLastError( ERROR_INVALID_ACCESS
);
715 if (!(wptr
= HeapAlloc( GetProcessHeap(), 0, length
* sizeof(WCHAR
) )))
717 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
720 if ((ret
= ReadConsoleOutputCharacterW( handle
, wptr
, length
, coord
, &read
)))
722 read
= WideCharToMultiByte( GetConsoleOutputCP(), 0, wptr
, read
, buffer
, length
, NULL
, NULL
);
725 HeapFree( GetProcessHeap(), 0, wptr
);
730 /******************************************************************************
731 * ReadConsoleOutputCharacterW (kernelbase.@)
733 BOOL WINAPI DECLSPEC_HOTPATCH
ReadConsoleOutputCharacterW( HANDLE handle
, LPWSTR buffer
, DWORD length
,
734 COORD coord
, DWORD
*count
)
738 TRACE( "(%p,%p,%d,%dx%d,%p)\n", handle
, buffer
, length
, coord
.X
, coord
.Y
, count
);
742 SetLastError( ERROR_INVALID_ACCESS
);
747 SERVER_START_REQ( read_console_output
)
749 req
->handle
= console_handle_unmap( handle
);
752 req
->mode
= CHAR_INFO_MODE_TEXT
;
754 wine_server_set_reply( req
, buffer
, length
* sizeof(WCHAR
) );
755 if ((ret
= !wine_server_call_err( req
))) *count
= wine_server_reply_size(reply
) / sizeof(WCHAR
);
762 /******************************************************************************
763 * ReadConsoleOutputA (kernelbase.@)
765 BOOL WINAPI DECLSPEC_HOTPATCH
ReadConsoleOutputA( HANDLE handle
, CHAR_INFO
*buffer
, COORD size
,
766 COORD coord
, SMALL_RECT
*region
)
771 ret
= ReadConsoleOutputW( handle
, buffer
, size
, coord
, region
);
772 if (ret
&& region
->Right
>= region
->Left
)
774 for (y
= 0; y
<= region
->Bottom
- region
->Top
; y
++)
775 char_info_WtoA( &buffer
[(coord
.Y
+ y
) * size
.X
+ coord
.X
], region
->Right
- region
->Left
+ 1 );
781 /******************************************************************************
782 * ReadConsoleOutputW (kernelbase.@)
784 BOOL WINAPI DECLSPEC_HOTPATCH
ReadConsoleOutputW( HANDLE handle
, CHAR_INFO
*buffer
, COORD size
,
785 COORD coord
, SMALL_RECT
*region
)
787 int width
, height
, y
;
790 width
= min( region
->Right
- region
->Left
+ 1, size
.X
- coord
.X
);
791 height
= min( region
->Bottom
- region
->Top
+ 1, size
.Y
- coord
.Y
);
793 if (width
> 0 && height
> 0)
795 for (y
= 0; y
< height
; y
++)
797 SERVER_START_REQ( read_console_output
)
799 req
->handle
= console_handle_unmap( handle
);
800 req
->x
= region
->Left
;
801 req
->y
= region
->Top
+ y
;
802 req
->mode
= CHAR_INFO_MODE_TEXTATTR
;
804 wine_server_set_reply( req
, &buffer
[(y
+coord
.Y
) * size
.X
+ coord
.X
],
805 width
* sizeof(CHAR_INFO
) );
806 if ((ret
= !wine_server_call_err( req
)))
808 width
= min( width
, reply
->width
- region
->Left
);
809 height
= min( height
, reply
->height
- region
->Top
);
816 region
->Bottom
= region
->Top
+ height
- 1;
817 region
->Right
= region
->Left
+ width
- 1;
822 /******************************************************************************
823 * ScrollConsoleScreenBufferA (kernelbase.@)
825 BOOL WINAPI DECLSPEC_HOTPATCH
ScrollConsoleScreenBufferA( HANDLE handle
, SMALL_RECT
*scroll
,
826 SMALL_RECT
*clip
, COORD origin
, CHAR_INFO
*fill
)
830 ciW
.Attributes
= fill
->Attributes
;
831 MultiByteToWideChar( GetConsoleOutputCP(), 0, &fill
->Char
.AsciiChar
, 1, &ciW
.Char
.UnicodeChar
, 1 );
833 return ScrollConsoleScreenBufferW( handle
, scroll
, clip
, origin
, &ciW
);
837 /******************************************************************************
838 * ScrollConsoleScreenBufferW (kernelbase.@)
840 BOOL WINAPI DECLSPEC_HOTPATCH
ScrollConsoleScreenBufferW( HANDLE handle
, SMALL_RECT
*scroll
,
841 SMALL_RECT
*clip_rect
, COORD origin
,
844 CONSOLE_SCREEN_BUFFER_INFO info
;
845 SMALL_RECT dst
, clip
;
846 int i
, j
, start
= -1;
852 TRACE( "(%p,(%d,%d-%d,%d),(%d,%d-%d,%d),%d-%d,%p)\n", handle
,
853 scroll
->Left
, scroll
->Top
, scroll
->Right
, scroll
->Bottom
,
854 clip_rect
->Left
, clip_rect
->Top
, clip_rect
->Right
, clip_rect
->Bottom
,
855 origin
.X
, origin
.Y
, fill
);
857 TRACE("(%p,(%d,%d-%d,%d),(nil),%d-%d,%p)\n", handle
,
858 scroll
->Left
, scroll
->Top
, scroll
->Right
, scroll
->Bottom
,
859 origin
.X
, origin
.Y
, fill
);
861 if (!GetConsoleScreenBufferInfo( handle
, &info
)) return FALSE
;
863 src
.X
= scroll
->Left
;
866 /* step 1: get dst rect */
869 dst
.Right
= dst
.Left
+ (scroll
->Right
- scroll
->Left
);
870 dst
.Bottom
= dst
.Top
+ (scroll
->Bottom
- scroll
->Top
);
872 /* step 2a: compute the final clip rect (optional passed clip and screen buffer limits */
875 clip
.Left
= max(0, clip_rect
->Left
);
876 clip
.Right
= min(info
.dwSize
.X
- 1, clip_rect
->Right
);
877 clip
.Top
= max(0, clip_rect
->Top
);
878 clip
.Bottom
= min(info
.dwSize
.Y
- 1, clip_rect
->Bottom
);
883 clip
.Right
= info
.dwSize
.X
- 1;
885 clip
.Bottom
= info
.dwSize
.Y
- 1;
887 if (clip
.Left
> clip
.Right
|| clip
.Top
> clip
.Bottom
) return FALSE
;
889 /* step 2b: clip dst rect */
890 if (dst
.Left
< clip
.Left
) {src
.X
+= clip
.Left
- dst
.Left
; dst
.Left
= clip
.Left
;}
891 if (dst
.Top
< clip
.Top
) {src
.Y
+= clip
.Top
- dst
.Top
; dst
.Top
= clip
.Top
;}
892 if (dst
.Right
> clip
.Right
) dst
.Right
= clip
.Right
;
893 if (dst
.Bottom
> clip
.Bottom
) dst
.Bottom
= clip
.Bottom
;
895 /* step 3: transfer the bits */
896 SERVER_START_REQ( move_console_output
)
898 req
->handle
= console_handle_unmap( handle
);
901 req
->x_dst
= dst
.Left
;
902 req
->y_dst
= dst
.Top
;
903 req
->w
= dst
.Right
- dst
.Left
+ 1;
904 req
->h
= dst
.Bottom
- dst
.Top
+ 1;
905 ret
= !wine_server_call_err( req
);
909 if (!ret
) return FALSE
;
911 /* step 4: clean out the exposed part */
913 /* have to write cell [i,j] if it is not in dst rect (because it has already
914 * been written to by the scroll) and is in clip (we shall not write
917 for (j
= max(scroll
->Top
, clip
.Top
); j
<= min(scroll
->Bottom
, clip
.Bottom
); j
++)
919 inside
= dst
.Top
<= j
&& j
<= dst
.Bottom
;
921 for (i
= max(scroll
->Left
, clip
.Left
); i
<= min(scroll
->Right
, clip
.Right
); i
++)
923 if (inside
&& dst
.Left
<= i
&& i
<= dst
.Right
)
927 fill_console_output( handle
, start
, j
, i
- start
, fill
);
933 if (start
== -1) start
= i
;
936 if (start
!= -1) fill_console_output( handle
, start
, j
, i
- start
, fill
);
943 /******************************************************************************
944 * SetConsoleActiveScreenBuffer (kernelbase.@)
946 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleActiveScreenBuffer( HANDLE handle
)
950 TRACE( "(%p)\n", handle
);
952 SERVER_START_REQ( set_console_input_info
)
955 req
->mask
= SET_CONSOLE_INPUT_INFO_ACTIVE_SB
;
956 req
->active_sb
= wine_server_obj_handle( handle
);
957 ret
= !wine_server_call_err( req
);
964 /******************************************************************************
965 * SetConsoleCP (kernelbase.@)
967 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleCP( UINT cp
)
971 if (!IsValidCodePage( cp
))
973 SetLastError( ERROR_INVALID_PARAMETER
);
976 SERVER_START_REQ( set_console_input_info
)
979 req
->mask
= SET_CONSOLE_INPUT_INFO_INPUT_CODEPAGE
;
981 ret
= !wine_server_call_err( req
);
988 /******************************************************************************
989 * SetConsoleCursorInfo (kernelbase.@)
991 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleCursorInfo( HANDLE handle
, CONSOLE_CURSOR_INFO
*info
)
995 TRACE( "(%p,%d,%d)\n", handle
, info
->dwSize
, info
->bVisible
);
997 SERVER_START_REQ( set_console_output_info
)
999 req
->handle
= console_handle_unmap( handle
);
1000 req
->cursor_size
= info
->dwSize
;
1001 req
->cursor_visible
= info
->bVisible
;
1002 req
->mask
= SET_CONSOLE_OUTPUT_INFO_CURSOR_GEOM
;
1003 ret
= !wine_server_call_err( req
);
1010 /******************************************************************************
1011 * SetConsoleCursorPosition (kernelbase.@)
1013 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleCursorPosition( HANDLE handle
, COORD pos
)
1015 CONSOLE_SCREEN_BUFFER_INFO info
;
1016 int w
, h
, do_move
= 0;
1019 TRACE( "%p %d %d\n", handle
, pos
.X
, pos
.Y
);
1021 SERVER_START_REQ( set_console_output_info
)
1023 req
->handle
= console_handle_unmap( handle
);
1024 req
->cursor_x
= pos
.X
;
1025 req
->cursor_y
= pos
.Y
;
1026 req
->mask
= SET_CONSOLE_OUTPUT_INFO_CURSOR_POS
;
1027 ret
= !wine_server_call_err( req
);
1031 if (!ret
|| !GetConsoleScreenBufferInfo( handle
, &info
)) return FALSE
;
1033 /* if cursor is no longer visible, scroll the visible window... */
1034 w
= info
.srWindow
.Right
- info
.srWindow
.Left
+ 1;
1035 h
= info
.srWindow
.Bottom
- info
.srWindow
.Top
+ 1;
1036 if (pos
.X
< info
.srWindow
.Left
)
1038 info
.srWindow
.Left
= min(pos
.X
, info
.dwSize
.X
- w
);
1041 else if (pos
.X
> info
.srWindow
.Right
)
1043 info
.srWindow
.Left
= max(pos
.X
, w
) - w
+ 1;
1046 info
.srWindow
.Right
= info
.srWindow
.Left
+ w
- 1;
1048 if (pos
.Y
< info
.srWindow
.Top
)
1050 info
.srWindow
.Top
= min(pos
.Y
, info
.dwSize
.Y
- h
);
1053 else if (pos
.Y
> info
.srWindow
.Bottom
)
1055 info
.srWindow
.Top
= max(pos
.Y
, h
) - h
+ 1;
1058 info
.srWindow
.Bottom
= info
.srWindow
.Top
+ h
- 1;
1060 if (do_move
) ret
= SetConsoleWindowInfo( handle
, TRUE
, &info
.srWindow
);
1065 /******************************************************************************
1066 * SetConsoleInputExeNameA (kernelbase.@)
1068 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleInputExeNameA( LPCSTR name
)
1070 if (!name
|| !name
[0])
1072 SetLastError( ERROR_INVALID_PARAMETER
);
1075 RtlEnterCriticalSection( &console_section
);
1076 MultiByteToWideChar( CP_ACP
, 0, name
, -1, input_exe
, ARRAY_SIZE(input_exe
) );
1077 RtlLeaveCriticalSection( &console_section
);
1082 /******************************************************************************
1083 * SetConsoleInputExeNameW (kernelbase.@)
1085 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleInputExeNameW( LPCWSTR name
)
1087 if (!name
|| !name
[0])
1089 SetLastError( ERROR_INVALID_PARAMETER
);
1092 RtlEnterCriticalSection( &console_section
);
1093 lstrcpynW( input_exe
, name
, ARRAY_SIZE(input_exe
) );
1094 RtlLeaveCriticalSection( &console_section
);
1099 /******************************************************************************
1100 * SetConsoleMode (kernelbase.@)
1102 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleMode( HANDLE handle
, DWORD mode
)
1106 SERVER_START_REQ(set_console_mode
)
1108 req
->handle
= console_handle_unmap( handle
);
1110 ret
= !wine_server_call_err( req
);
1114 TRACE( "(%p,%x) retval == %d\n", handle
, mode
, ret
);
1119 /******************************************************************************
1120 * SetConsoleOutputCP (kernelbase.@)
1122 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleOutputCP( UINT cp
)
1126 if (!IsValidCodePage( cp
))
1128 SetLastError( ERROR_INVALID_PARAMETER
);
1131 SERVER_START_REQ( set_console_input_info
)
1134 req
->mask
= SET_CONSOLE_INPUT_INFO_OUTPUT_CODEPAGE
;
1135 req
->output_cp
= cp
;
1136 ret
= !wine_server_call_err( req
);
1143 /******************************************************************************
1144 * SetConsoleScreenBufferInfoEx (kernelbase.@)
1146 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleScreenBufferInfoEx( HANDLE handle
,
1147 CONSOLE_SCREEN_BUFFER_INFOEX
*info
)
1151 TRACE("(%p, %p)\n", handle
, info
);
1153 if (info
->cbSize
!= sizeof(CONSOLE_SCREEN_BUFFER_INFOEX
))
1155 SetLastError(ERROR_INVALID_PARAMETER
);
1159 SERVER_START_REQ( set_console_output_info
)
1161 req
->handle
= console_handle_unmap( handle
);
1162 req
->mask
= SET_CONSOLE_OUTPUT_INFO_CURSOR_POS
| SET_CONSOLE_OUTPUT_INFO_SIZE
|
1163 SET_CONSOLE_OUTPUT_INFO_ATTR
| SET_CONSOLE_OUTPUT_INFO_POPUP_ATTR
|
1164 SET_CONSOLE_OUTPUT_INFO_DISPLAY_WINDOW
| SET_CONSOLE_OUTPUT_INFO_MAX_SIZE
;
1165 req
->width
= info
->dwSize
.X
;
1166 req
->height
= info
->dwSize
.Y
;
1167 req
->cursor_x
= info
->dwCursorPosition
.X
;
1168 req
->cursor_y
= info
->dwCursorPosition
.Y
;
1169 req
->attr
= info
->wAttributes
;
1170 req
->win_left
= info
->srWindow
.Left
;
1171 req
->win_top
= info
->srWindow
.Top
;
1172 req
->win_right
= info
->srWindow
.Right
;
1173 req
->win_bottom
= info
->srWindow
.Bottom
;
1174 req
->popup_attr
= info
->wPopupAttributes
;
1175 req
->max_width
= min( info
->dwMaximumWindowSize
.X
, info
->dwSize
.X
);
1176 req
->max_height
= min( info
->dwMaximumWindowSize
.Y
, info
->dwSize
.Y
);
1177 ret
= !wine_server_call_err( req
);
1185 /******************************************************************************
1186 * SetConsoleScreenBufferSize (kernelbase.@)
1188 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleScreenBufferSize( HANDLE handle
, COORD size
)
1192 TRACE( "(%p,(%d,%d))\n", handle
, size
.X
, size
.Y
);
1193 SERVER_START_REQ( set_console_output_info
)
1195 req
->handle
= console_handle_unmap( handle
);
1196 req
->width
= size
.X
;
1197 req
->height
= size
.Y
;
1198 req
->mask
= SET_CONSOLE_OUTPUT_INFO_SIZE
;
1199 ret
= !wine_server_call_err( req
);
1206 /******************************************************************************
1207 * SetConsoleTextAttribute (kernelbase.@)
1209 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleTextAttribute( HANDLE handle
, WORD attr
)
1213 TRACE( "(%p,%d)\n", handle
, attr
);
1214 SERVER_START_REQ( set_console_output_info
)
1216 req
->handle
= console_handle_unmap( handle
);
1218 req
->mask
= SET_CONSOLE_OUTPUT_INFO_ATTR
;
1219 ret
= !wine_server_call_err( req
);
1226 /******************************************************************************
1227 * SetConsoleTitleW (kernelbase.@)
1229 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleTitleW( LPCWSTR title
)
1233 TRACE( "%s\n", debugstr_w( title
));
1234 SERVER_START_REQ( set_console_input_info
)
1237 req
->mask
= SET_CONSOLE_INPUT_INFO_TITLE
;
1238 wine_server_add_data( req
, title
, lstrlenW(title
) * sizeof(WCHAR
) );
1239 ret
= !wine_server_call_err( req
);
1246 /******************************************************************************
1247 * SetConsoleWindowInfo (kernelbase.@)
1249 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleWindowInfo( HANDLE handle
, BOOL absolute
, SMALL_RECT
*window
)
1251 SMALL_RECT rect
= *window
;
1254 TRACE( "(%p,%d,(%d,%d-%d,%d))\n", handle
, absolute
, rect
.Left
, rect
.Top
, rect
.Right
, rect
.Bottom
);
1258 CONSOLE_SCREEN_BUFFER_INFO info
;
1260 if (!GetConsoleScreenBufferInfo( handle
, &info
)) return FALSE
;
1261 rect
.Left
+= info
.srWindow
.Left
;
1262 rect
.Top
+= info
.srWindow
.Top
;
1263 rect
.Right
+= info
.srWindow
.Right
;
1264 rect
.Bottom
+= info
.srWindow
.Bottom
;
1266 SERVER_START_REQ( set_console_output_info
)
1268 req
->handle
= console_handle_unmap( handle
);
1269 req
->win_left
= rect
.Left
;
1270 req
->win_top
= rect
.Top
;
1271 req
->win_right
= rect
.Right
;
1272 req
->win_bottom
= rect
.Bottom
;
1273 req
->mask
= SET_CONSOLE_OUTPUT_INFO_DISPLAY_WINDOW
;
1274 ret
= !wine_server_call_err( req
);
1282 /******************************************************************************
1283 * WriteConsoleInputA (kernelbase.@)
1285 BOOL WINAPI DECLSPEC_HOTPATCH
WriteConsoleInputA( HANDLE handle
, const INPUT_RECORD
*buffer
,
1286 DWORD count
, DWORD
*written
)
1288 INPUT_RECORD
*recW
= NULL
;
1295 SetLastError( ERROR_INVALID_ACCESS
);
1298 if (!(recW
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(*recW
) )))
1300 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1303 memcpy( recW
, buffer
, count
* sizeof(*recW
) );
1304 input_records_AtoW( recW
, count
);
1306 ret
= WriteConsoleInputW( handle
, recW
, count
, written
);
1307 HeapFree( GetProcessHeap(), 0, recW
);
1312 /******************************************************************************
1313 * WriteConsoleInputW (kernelbase.@)
1315 BOOL WINAPI DECLSPEC_HOTPATCH
WriteConsoleInputW( HANDLE handle
, const INPUT_RECORD
*buffer
,
1316 DWORD count
, DWORD
*written
)
1318 DWORD events_written
= 0;
1321 TRACE( "(%p,%p,%d,%p)\n", handle
, buffer
, count
, written
);
1323 if (count
> 0 && !buffer
)
1325 SetLastError( ERROR_INVALID_ACCESS
);
1328 SERVER_START_REQ( write_console_input
)
1330 req
->handle
= console_handle_unmap( handle
);
1331 wine_server_add_data( req
, buffer
, count
* sizeof(INPUT_RECORD
) );
1332 if ((ret
= !wine_server_call_err( req
))) events_written
= reply
->written
;
1336 if (written
) *written
= events_written
;
1339 SetLastError( ERROR_INVALID_ACCESS
);
1346 /***********************************************************************
1347 * WriteConsoleOutputA (kernelbase.@)
1349 BOOL WINAPI DECLSPEC_HOTPATCH
WriteConsoleOutputA( HANDLE handle
, const CHAR_INFO
*buffer
,
1350 COORD size
, COORD coord
, SMALL_RECT
*region
)
1354 COORD new_size
, new_coord
;
1357 new_size
.X
= min( region
->Right
- region
->Left
+ 1, size
.X
- coord
.X
);
1358 new_size
.Y
= min( region
->Bottom
- region
->Top
+ 1, size
.Y
- coord
.Y
);
1360 if (new_size
.X
<= 0 || new_size
.Y
<= 0)
1362 region
->Bottom
= region
->Top
+ new_size
.Y
- 1;
1363 region
->Right
= region
->Left
+ new_size
.X
- 1;
1367 /* only copy the useful rectangle */
1368 if (!(ciW
= HeapAlloc( GetProcessHeap(), 0, sizeof(CHAR_INFO
) * new_size
.X
* new_size
.Y
)))
1370 for (y
= 0; y
< new_size
.Y
; y
++)
1371 memcpy( &ciW
[y
* new_size
.X
], &buffer
[(y
+ coord
.Y
) * size
.X
+ coord
.X
],
1372 new_size
.X
* sizeof(CHAR_INFO
) );
1373 char_info_AtoW( ciW
, new_size
.X
* new_size
.Y
);
1374 new_coord
.X
= new_coord
.Y
= 0;
1375 ret
= WriteConsoleOutputW( handle
, ciW
, new_size
, new_coord
, region
);
1376 HeapFree( GetProcessHeap(), 0, ciW
);
1381 /***********************************************************************
1382 * WriteConsoleOutputW (kernelbase.@)
1384 BOOL WINAPI DECLSPEC_HOTPATCH
WriteConsoleOutputW( HANDLE handle
, const CHAR_INFO
*buffer
,
1385 COORD size
, COORD coord
, SMALL_RECT
*region
)
1387 int width
, height
, y
;
1390 TRACE( "(%p,%p,(%d,%d),(%d,%d),(%d,%dx%d,%d)\n",
1391 handle
, buffer
, size
.X
, size
.Y
, coord
.X
, coord
.Y
,
1392 region
->Left
, region
->Top
, region
->Right
, region
->Bottom
);
1394 width
= min( region
->Right
- region
->Left
+ 1, size
.X
- coord
.X
);
1395 height
= min( region
->Bottom
- region
->Top
+ 1, size
.Y
- coord
.Y
);
1397 if (width
> 0 && height
> 0)
1399 for (y
= 0; y
< height
; y
++)
1401 SERVER_START_REQ( write_console_output
)
1403 req
->handle
= console_handle_unmap( handle
);
1404 req
->x
= region
->Left
;
1405 req
->y
= region
->Top
+ y
;
1406 req
->mode
= CHAR_INFO_MODE_TEXTATTR
;
1408 wine_server_add_data( req
, &buffer
[(y
+ coord
.Y
) * size
.X
+ coord
.X
],
1409 width
* sizeof(CHAR_INFO
));
1410 if ((ret
= !wine_server_call_err( req
)))
1412 width
= min( width
, reply
->width
- region
->Left
);
1413 height
= min( height
, reply
->height
- region
->Top
);
1420 region
->Bottom
= region
->Top
+ height
- 1;
1421 region
->Right
= region
->Left
+ width
- 1;
1426 /******************************************************************************
1427 * WriteConsoleOutputAttribute (kernelbase.@)
1429 BOOL WINAPI DECLSPEC_HOTPATCH
WriteConsoleOutputAttribute( HANDLE handle
, const WORD
*attr
, DWORD length
,
1430 COORD coord
, DWORD
*written
)
1434 TRACE( "(%p,%p,%d,%dx%d,%p)\n", handle
, attr
, length
, coord
.X
, coord
.Y
, written
);
1436 if ((length
> 0 && !attr
) || !written
)
1438 SetLastError( ERROR_INVALID_ACCESS
);
1443 SERVER_START_REQ( write_console_output
)
1445 req
->handle
= console_handle_unmap( handle
);
1448 req
->mode
= CHAR_INFO_MODE_ATTR
;
1450 wine_server_add_data( req
, attr
, length
* sizeof(WORD
) );
1451 if ((ret
= !wine_server_call_err( req
))) *written
= reply
->written
;
1458 /******************************************************************************
1459 * WriteConsoleOutputCharacterA (kernelbase.@)
1461 BOOL WINAPI DECLSPEC_HOTPATCH
WriteConsoleOutputCharacterA( HANDLE handle
, LPCSTR str
, DWORD length
,
1462 COORD coord
, DWORD
*written
)
1468 TRACE( "(%p,%s,%d,%dx%d,%p)\n", handle
, debugstr_an(str
, length
), length
, coord
.X
, coord
.Y
, written
);
1474 SetLastError( ERROR_INVALID_ACCESS
);
1477 lenW
= MultiByteToWideChar( GetConsoleOutputCP(), 0, str
, length
, NULL
, 0 );
1479 if (!(strW
= HeapAlloc( GetProcessHeap(), 0, lenW
* sizeof(WCHAR
) )))
1481 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1484 MultiByteToWideChar( GetConsoleOutputCP(), 0, str
, length
, strW
, lenW
);
1486 ret
= WriteConsoleOutputCharacterW( handle
, strW
, lenW
, coord
, written
);
1487 HeapFree( GetProcessHeap(), 0, strW
);
1492 /******************************************************************************
1493 * WriteConsoleOutputCharacterW (kernelbase.@)
1495 BOOL WINAPI DECLSPEC_HOTPATCH
WriteConsoleOutputCharacterW( HANDLE handle
, LPCWSTR str
, DWORD length
,
1496 COORD coord
, DWORD
*written
)
1500 TRACE( "(%p,%s,%d,%dx%d,%p)\n", handle
, debugstr_wn(str
, length
), length
, coord
.X
, coord
.Y
, written
);
1502 if ((length
> 0 && !str
) || !written
)
1504 SetLastError( ERROR_INVALID_ACCESS
);
1509 SERVER_START_REQ( write_console_output
)
1511 req
->handle
= console_handle_unmap( handle
);
1514 req
->mode
= CHAR_INFO_MODE_TEXT
;
1516 wine_server_add_data( req
, str
, length
* sizeof(WCHAR
) );
1517 if ((ret
= !wine_server_call_err( req
))) *written
= reply
->written
;