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/condrv.h"
40 #include "wine/server.h"
41 #include "wine/exception.h"
42 #include "wine/debug.h"
43 #include "kernelbase.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(console
);
48 static CRITICAL_SECTION console_section
;
49 static CRITICAL_SECTION_DEBUG critsect_debug
=
51 0, 0, &console_section
,
52 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
53 0, 0, { (DWORD_PTR
)(__FILE__
": console_section") }
55 static CRITICAL_SECTION console_section
= { &critsect_debug
, -1, 0, 0, 0, 0 };
57 static HANDLE console_wait_event
;
59 static WCHAR input_exe
[MAX_PATH
+ 1];
63 PHANDLER_ROUTINE func
;
64 struct ctrl_handler
*next
;
67 static BOOL WINAPI
default_ctrl_handler( DWORD type
)
69 FIXME( "Terminating process %x on event %x\n", GetCurrentProcessId(), type
);
70 RtlExitUserProcess( 0 );
74 static struct ctrl_handler default_handler
= { default_ctrl_handler
, NULL
};
75 static struct ctrl_handler
*ctrl_handlers
= &default_handler
;
77 /* map a kernel32 console handle onto a real wineserver handle */
78 static inline obj_handle_t
console_handle_unmap( HANDLE h
)
80 return wine_server_obj_handle( console_handle_map( h
) );
83 static BOOL
console_ioctl( HANDLE handle
, DWORD code
, void *in_buff
, DWORD in_count
,
84 void *out_buff
, DWORD out_count
, DWORD
*read
)
89 status
= NtDeviceIoControlFile( handle
, NULL
, NULL
, NULL
, &io
, code
, in_buff
, in_count
,
90 out_buff
, out_count
);
94 if (read
) *read
= io
.Information
;
96 case STATUS_INVALID_PARAMETER
:
99 status
= STATUS_INVALID_HANDLE
;
103 return set_ntstatus( status
);
106 /* map input records to ASCII */
107 static void input_records_WtoA( INPUT_RECORD
*buffer
, int count
)
109 UINT cp
= GetConsoleCP();
113 for (i
= 0; i
< count
; i
++)
115 if (buffer
[i
].EventType
!= KEY_EVENT
) continue;
116 WideCharToMultiByte( cp
, 0, &buffer
[i
].Event
.KeyEvent
.uChar
.UnicodeChar
, 1, &ch
, 1, NULL
, NULL
);
117 buffer
[i
].Event
.KeyEvent
.uChar
.AsciiChar
= ch
;
121 /* map input records to Unicode */
122 static void input_records_AtoW( INPUT_RECORD
*buffer
, int count
)
124 UINT cp
= GetConsoleCP();
128 for (i
= 0; i
< count
; i
++)
130 if (buffer
[i
].EventType
!= KEY_EVENT
) continue;
131 MultiByteToWideChar( cp
, 0, &buffer
[i
].Event
.KeyEvent
.uChar
.AsciiChar
, 1, &ch
, 1 );
132 buffer
[i
].Event
.KeyEvent
.uChar
.UnicodeChar
= ch
;
136 /* map char infos to ASCII */
137 static void char_info_WtoA( UINT cp
, CHAR_INFO
*buffer
, int count
)
143 WideCharToMultiByte( cp
, 0, &buffer
->Char
.UnicodeChar
, 1, &ch
, 1, NULL
, NULL
);
144 buffer
->Char
.AsciiChar
= ch
;
149 /* map char infos to Unicode */
150 static void char_info_AtoW( CHAR_INFO
*buffer
, int count
)
152 UINT cp
= GetConsoleOutputCP();
157 MultiByteToWideChar( cp
, 0, &buffer
->Char
.AsciiChar
, 1, &ch
, 1 );
158 buffer
->Char
.UnicodeChar
= ch
;
163 /* helper function for ScrollConsoleScreenBufferW */
164 static void fill_console_output( HANDLE handle
, int i
, int j
, int len
, CHAR_INFO
*fill
)
166 struct condrv_fill_output_params params
;
168 params
.mode
= CHAR_INFO_MODE_TEXTATTR
;
173 params
.ch
= fill
->Char
.UnicodeChar
;
174 params
.attr
= fill
->Attributes
;
175 console_ioctl( handle
, IOCTL_CONDRV_FILL_OUTPUT
, ¶ms
, sizeof(params
), NULL
, 0, NULL
);
178 /* helper function for GetLargestConsoleWindowSize */
179 static COORD
get_largest_console_window_size( HANDLE handle
)
181 struct condrv_output_info info
;
184 if (!console_ioctl( handle
, IOCTL_CONDRV_GET_OUTPUT_INFO
, NULL
, 0, &info
, sizeof(info
), NULL
))
187 c
.X
= info
.max_width
;
188 c
.Y
= info
.max_height
;
189 TRACE( "(%p), returning %dx%d\n", handle
, c
.X
, c
.Y
);
193 /******************************************************************
194 * AttachConsole (kernelbase.@)
196 BOOL WINAPI DECLSPEC_HOTPATCH
AttachConsole( DWORD pid
)
200 TRACE( "(%x)\n", pid
);
202 SERVER_START_REQ( attach_console
)
205 if ((ret
= !wine_server_call_err( req
)))
207 SetStdHandle( STD_INPUT_HANDLE
, wine_server_ptr_handle( reply
->std_in
));
208 SetStdHandle( STD_OUTPUT_HANDLE
, wine_server_ptr_handle( reply
->std_out
));
209 SetStdHandle( STD_ERROR_HANDLE
, wine_server_ptr_handle( reply
->std_err
));
217 /******************************************************************
218 * AllocConsole (kernelbase.@)
220 BOOL WINAPI
AllocConsole(void)
222 SECURITY_ATTRIBUTES inheritable_attr
= { sizeof(inheritable_attr
), NULL
, TRUE
};
223 HANDLE std_in
= INVALID_HANDLE_VALUE
;
224 HANDLE std_out
= INVALID_HANDLE_VALUE
;
225 HANDLE std_err
= INVALID_HANDLE_VALUE
;
226 STARTUPINFOW app_si
, console_si
;
227 WCHAR buffer
[1024], cmd
[256];
228 PROCESS_INFORMATION pi
;
235 std_in
= CreateFileW( L
"CONIN$", GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
, 0, NULL
, OPEN_EXISTING
, 0, 0 );
236 if (GetConsoleMode( std_in
, &mode
))
238 /* we already have a console opened on this process, don't create a new one */
239 CloseHandle( std_in
);
243 GetStartupInfoW(&app_si
);
245 memset(&console_si
, 0, sizeof(console_si
));
246 console_si
.cb
= sizeof(console_si
);
247 /* setup a view arguments for wineconsole (it'll use them as default values) */
248 if (app_si
.dwFlags
& STARTF_USECOUNTCHARS
)
250 console_si
.dwFlags
|= STARTF_USECOUNTCHARS
;
251 console_si
.dwXCountChars
= app_si
.dwXCountChars
;
252 console_si
.dwYCountChars
= app_si
.dwYCountChars
;
254 if (app_si
.dwFlags
& STARTF_USEFILLATTRIBUTE
)
256 console_si
.dwFlags
|= STARTF_USEFILLATTRIBUTE
;
257 console_si
.dwFillAttribute
= app_si
.dwFillAttribute
;
259 if (app_si
.dwFlags
& STARTF_USESHOWWINDOW
)
261 console_si
.dwFlags
|= STARTF_USESHOWWINDOW
;
262 console_si
.wShowWindow
= app_si
.wShowWindow
;
265 console_si
.lpTitle
= app_si
.lpTitle
;
266 else if (GetModuleFileNameW(0, buffer
, ARRAY_SIZE(buffer
)))
268 buffer
[ARRAY_SIZE(buffer
) - 1] = 0;
269 console_si
.lpTitle
= buffer
;
272 if (!(event
= CreateEventW( &inheritable_attr
, TRUE
, FALSE
, NULL
))) return FALSE
;
274 swprintf( cmd
, ARRAY_SIZE(cmd
), L
"wineconsole --use-event=%ld", (DWORD_PTR
)event
);
275 if ((ret
= CreateProcessW( NULL
, cmd
, NULL
, NULL
, TRUE
, DETACHED_PROCESS
, NULL
, NULL
, &console_si
, &pi
)))
277 HANDLE wait_handles
[2] = { event
, pi
.hProcess
};
278 ret
= WaitForMultipleObjects( ARRAY_SIZE(wait_handles
), wait_handles
, FALSE
, INFINITE
) == WAIT_OBJECT_0
;
279 CloseHandle( pi
.hThread
);
280 CloseHandle( pi
.hProcess
);
282 CloseHandle( event
);
283 if (!ret
) goto error
;
284 TRACE( "Started wineconsole pid=%08x tid=%08x\n", pi
.dwProcessId
, pi
.dwThreadId
);
286 if (!(app_si
.dwFlags
& STARTF_USESTDHANDLES
))
289 std_in
= CreateFileW( L
"CONIN$", GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
, 0, &inheritable_attr
,
290 OPEN_EXISTING
, 0, 0);
291 if (std_in
== INVALID_HANDLE_VALUE
) goto error
;
293 std_out
= CreateFileW( L
"CONOUT$", GENERIC_READ
| GENERIC_WRITE
, 0, &inheritable_attr
, OPEN_EXISTING
, 0, 0);
294 if (std_out
== INVALID_HANDLE_VALUE
) goto error
;
296 if (!DuplicateHandle( GetCurrentProcess(), std_out
, GetCurrentProcess(),
297 &std_err
, 0, TRUE
, DUPLICATE_SAME_ACCESS
) )
302 std_in
= app_si
.hStdInput
;
303 std_out
= app_si
.hStdOutput
;
304 std_err
= app_si
.hStdError
;
307 SetStdHandle( STD_INPUT_HANDLE
, std_in
);
308 SetStdHandle( STD_OUTPUT_HANDLE
, std_out
);
309 SetStdHandle( STD_ERROR_HANDLE
, std_err
);
310 SetLastError( ERROR_SUCCESS
);
314 ERR("Can't allocate console\n");
315 if (std_in
!= INVALID_HANDLE_VALUE
) CloseHandle(std_in
);
316 if (std_out
!= INVALID_HANDLE_VALUE
) CloseHandle(std_out
);
317 if (std_err
!= INVALID_HANDLE_VALUE
) CloseHandle(std_err
);
323 /******************************************************************************
324 * CreateConsoleScreenBuffer (kernelbase.@)
326 HANDLE WINAPI DECLSPEC_HOTPATCH
CreateConsoleScreenBuffer( DWORD access
, DWORD share
,
327 SECURITY_ATTRIBUTES
*sa
, DWORD flags
,
330 OBJECT_ATTRIBUTES attr
= {sizeof(attr
)};
331 IO_STATUS_BLOCK iosb
;
336 TRACE( "(%x,%x,%p,%x,%p)\n", access
, share
, sa
, flags
, data
);
338 if (flags
!= CONSOLE_TEXTMODE_BUFFER
|| data
)
340 SetLastError( ERROR_INVALID_PARAMETER
);
341 return INVALID_HANDLE_VALUE
;
344 RtlInitUnicodeString( &name
, L
"\\Device\\ConDrv\\ScreenBuffer" );
345 attr
.ObjectName
= &name
;
346 attr
.SecurityDescriptor
= sa
? sa
->lpSecurityDescriptor
: NULL
;
347 if (sa
&& sa
->bInheritHandle
) attr
.Attributes
|= OBJ_INHERIT
;
348 status
= NtCreateFile( &handle
, access
, &attr
, &iosb
, NULL
, FILE_ATTRIBUTE_NORMAL
, 0, FILE_OPEN
,
349 FILE_NON_DIRECTORY_FILE
, NULL
, 0 );
350 return set_ntstatus( status
) ? handle
: INVALID_HANDLE_VALUE
;
354 /******************************************************************************
355 * CtrlRoutine (kernelbase.@)
357 DWORD WINAPI
CtrlRoutine( void *arg
)
359 DWORD_PTR event
= (DWORD_PTR
)arg
;
360 struct ctrl_handler
*handler
;
362 if (event
== CTRL_C_EVENT
)
364 BOOL caught_by_dbg
= TRUE
;
365 /* First, try to pass the ctrl-C event to the debugger (if any)
366 * If it continues, there's nothing more to do
367 * Otherwise, we need to send the ctrl-C event to the handlers
371 RaiseException( DBG_CONTROL_C
, 0, 0, NULL
);
375 caught_by_dbg
= FALSE
;
378 if (caught_by_dbg
) return 0;
381 if (NtCurrentTeb()->Peb
->ProcessParameters
->ConsoleFlags
& 1) return 0;
383 RtlEnterCriticalSection( &console_section
);
384 for (handler
= ctrl_handlers
; handler
; handler
= handler
->next
)
386 if (handler
->func( event
)) break;
388 RtlLeaveCriticalSection( &console_section
);
393 /******************************************************************************
394 * FillConsoleOutputAttribute (kernelbase.@)
396 BOOL WINAPI DECLSPEC_HOTPATCH
FillConsoleOutputAttribute( HANDLE handle
, WORD attr
, DWORD length
,
397 COORD coord
, DWORD
*written
)
399 struct condrv_fill_output_params params
;
401 TRACE( "(%p,%d,%d,(%dx%d),%p)\n", handle
, attr
, length
, coord
.X
, coord
.Y
, written
);
405 SetLastError( ERROR_INVALID_ACCESS
);
411 params
.mode
= CHAR_INFO_MODE_ATTR
;
414 params
.count
= length
;
418 return console_ioctl( handle
, IOCTL_CONDRV_FILL_OUTPUT
, ¶ms
, sizeof(params
),
419 written
, sizeof(written
), NULL
);
423 /******************************************************************************
424 * FillConsoleOutputCharacterA (kernelbase.@)
426 BOOL WINAPI DECLSPEC_HOTPATCH
FillConsoleOutputCharacterA( HANDLE handle
, CHAR ch
, DWORD length
,
427 COORD coord
, DWORD
*written
)
431 MultiByteToWideChar( GetConsoleOutputCP(), 0, &ch
, 1, &wch
, 1 );
432 return FillConsoleOutputCharacterW( handle
, wch
, length
, coord
, written
);
436 /******************************************************************************
437 * FillConsoleOutputCharacterW (kernelbase.@)
439 BOOL WINAPI DECLSPEC_HOTPATCH
FillConsoleOutputCharacterW( HANDLE handle
, WCHAR ch
, DWORD length
,
440 COORD coord
, DWORD
*written
)
442 struct condrv_fill_output_params params
;
444 TRACE( "(%p,%s,%d,(%dx%d),%p)\n", handle
, debugstr_wn(&ch
, 1), length
, coord
.X
, coord
.Y
, written
);
448 SetLastError( ERROR_INVALID_ACCESS
);
454 params
.mode
= CHAR_INFO_MODE_TEXT
;
457 params
.count
= length
;
461 return console_ioctl( handle
, IOCTL_CONDRV_FILL_OUTPUT
, ¶ms
, sizeof(params
),
462 written
, sizeof(written
), NULL
);
465 HANDLE
get_console_wait_handle( HANDLE handle
)
469 SERVER_START_REQ( get_console_wait_event
)
471 req
->handle
= wine_server_obj_handle( console_handle_map( handle
));
472 if (!wine_server_call( req
)) event
= wine_server_ptr_handle( reply
->event
);
477 if (InterlockedCompareExchangePointer( &console_wait_event
, event
, 0 )) NtClose( event
);
478 handle
= console_wait_event
;
484 /***********************************************************************
485 * FreeConsole (kernelbase.@)
487 BOOL WINAPI DECLSPEC_HOTPATCH
FreeConsole(void)
492 SERVER_START_REQ( free_console
)
494 ret
= !wine_server_call_err( req
);
497 if ((event
= InterlockedExchangePointer( &console_wait_event
, NULL
))) NtClose( event
);
502 /******************************************************************************
503 * GenerateConsoleCtrlEvent (kernelbase.@)
505 BOOL WINAPI DECLSPEC_HOTPATCH
GenerateConsoleCtrlEvent( DWORD event
, DWORD group
)
509 TRACE( "(%d, %x)\n", event
, group
);
511 if (event
!= CTRL_C_EVENT
&& event
!= CTRL_BREAK_EVENT
)
513 ERR( "Invalid event %d for PGID %x\n", event
, group
);
517 SERVER_START_REQ( send_console_signal
)
520 req
->group_id
= group
;
521 ret
= !wine_server_call_err( req
);
528 /******************************************************************************
529 * GetConsoleCP (kernelbase.@)
531 UINT WINAPI DECLSPEC_HOTPATCH
GetConsoleCP(void)
533 UINT codepage
= GetOEMCP(); /* default value */
535 SERVER_START_REQ( get_console_input_info
)
538 if (!wine_server_call_err( req
))
540 if (reply
->input_cp
) codepage
= reply
->input_cp
;
548 /******************************************************************************
549 * GetConsoleCursorInfo (kernelbase.@)
551 BOOL WINAPI DECLSPEC_HOTPATCH
GetConsoleCursorInfo( HANDLE handle
, CONSOLE_CURSOR_INFO
*info
)
553 struct condrv_output_info condrv_info
;
555 if (!console_ioctl( handle
, IOCTL_CONDRV_GET_OUTPUT_INFO
, NULL
, 0, &condrv_info
, sizeof(condrv_info
), NULL
))
560 SetLastError( ERROR_INVALID_ACCESS
);
564 info
->dwSize
= condrv_info
.cursor_size
;
565 info
->bVisible
= condrv_info
.cursor_visible
;
566 TRACE("(%p) returning (%d,%d)\n", handle
, info
->dwSize
, info
->bVisible
);
571 /***********************************************************************
572 * GetConsoleInputExeNameA (kernelbase.@)
574 BOOL WINAPI DECLSPEC_HOTPATCH
GetConsoleInputExeNameA( DWORD len
, LPSTR buffer
)
576 RtlEnterCriticalSection( &console_section
);
577 if (WideCharToMultiByte( CP_ACP
, 0, input_exe
, -1, NULL
, 0, NULL
, NULL
) <= len
)
578 WideCharToMultiByte( CP_ACP
, 0, input_exe
, -1, buffer
, len
, NULL
, NULL
);
579 else SetLastError(ERROR_BUFFER_OVERFLOW
);
580 RtlLeaveCriticalSection( &console_section
);
585 /***********************************************************************
586 * GetConsoleInputExeNameW (kernelbase.@)
588 BOOL WINAPI DECLSPEC_HOTPATCH
GetConsoleInputExeNameW( DWORD len
, LPWSTR buffer
)
590 RtlEnterCriticalSection( &console_section
);
591 if (len
> lstrlenW(input_exe
)) lstrcpyW( buffer
, input_exe
);
592 else SetLastError( ERROR_BUFFER_OVERFLOW
);
593 RtlLeaveCriticalSection( &console_section
);
598 /***********************************************************************
599 * GetConsoleMode (kernelbase.@)
601 BOOL WINAPI DECLSPEC_HOTPATCH
GetConsoleMode( HANDLE handle
, DWORD
*mode
)
603 return console_ioctl( handle
, IOCTL_CONDRV_GET_MODE
, NULL
, 0, mode
, sizeof(*mode
), NULL
);
607 /***********************************************************************
608 * GetConsoleOutputCP (kernelbase.@)
610 UINT WINAPI DECLSPEC_HOTPATCH
GetConsoleOutputCP(void)
612 UINT codepage
= GetOEMCP(); /* default value */
614 SERVER_START_REQ( get_console_input_info
)
617 if (!wine_server_call_err( req
))
619 if (reply
->output_cp
) codepage
= reply
->output_cp
;
627 /***********************************************************************
628 * GetConsoleScreenBufferInfo (kernelbase.@)
630 BOOL WINAPI DECLSPEC_HOTPATCH
GetConsoleScreenBufferInfo( HANDLE handle
, CONSOLE_SCREEN_BUFFER_INFO
*info
)
632 struct condrv_output_info condrv_info
;
634 if (!console_ioctl( handle
, IOCTL_CONDRV_GET_OUTPUT_INFO
, NULL
, 0,
635 &condrv_info
, sizeof(condrv_info
), NULL
))
638 info
->dwSize
.X
= condrv_info
.width
;
639 info
->dwSize
.Y
= condrv_info
.height
;
640 info
->dwCursorPosition
.X
= condrv_info
.cursor_x
;
641 info
->dwCursorPosition
.Y
= condrv_info
.cursor_y
;
642 info
->wAttributes
= condrv_info
.attr
;
643 info
->srWindow
.Left
= condrv_info
.win_left
;
644 info
->srWindow
.Right
= condrv_info
.win_right
;
645 info
->srWindow
.Top
= condrv_info
.win_top
;
646 info
->srWindow
.Bottom
= condrv_info
.win_bottom
;
647 info
->dwMaximumWindowSize
.X
= min(condrv_info
.width
, condrv_info
.max_width
);
648 info
->dwMaximumWindowSize
.Y
= min(condrv_info
.height
, condrv_info
.max_height
);
650 TRACE( "(%p,(%d,%d) (%d,%d) %d (%d,%d-%d,%d) (%d,%d)\n", handle
,
651 info
->dwSize
.X
, info
->dwSize
.Y
, info
->dwCursorPosition
.X
, info
->dwCursorPosition
.Y
,
652 info
->wAttributes
, info
->srWindow
.Left
, info
->srWindow
.Top
, info
->srWindow
.Right
,
653 info
->srWindow
.Bottom
, info
->dwMaximumWindowSize
.X
, info
->dwMaximumWindowSize
.Y
);
658 /***********************************************************************
659 * GetConsoleScreenBufferInfoEx (kernelbase.@)
661 BOOL WINAPI DECLSPEC_HOTPATCH
GetConsoleScreenBufferInfoEx( HANDLE handle
,
662 CONSOLE_SCREEN_BUFFER_INFOEX
*info
)
664 struct condrv_output_info condrv_info
;
666 if (info
->cbSize
!= sizeof(CONSOLE_SCREEN_BUFFER_INFOEX
))
668 SetLastError( ERROR_INVALID_PARAMETER
);
672 if (!console_ioctl( handle
, IOCTL_CONDRV_GET_OUTPUT_INFO
, NULL
, 0, &condrv_info
,
673 sizeof(condrv_info
), NULL
))
676 info
->dwSize
.X
= condrv_info
.width
;
677 info
->dwSize
.Y
= condrv_info
.height
;
678 info
->dwCursorPosition
.X
= condrv_info
.cursor_x
;
679 info
->dwCursorPosition
.Y
= condrv_info
.cursor_y
;
680 info
->wAttributes
= condrv_info
.attr
;
681 info
->srWindow
.Left
= condrv_info
.win_left
;
682 info
->srWindow
.Top
= condrv_info
.win_top
;
683 info
->srWindow
.Right
= condrv_info
.win_right
;
684 info
->srWindow
.Bottom
= condrv_info
.win_bottom
;
685 info
->dwMaximumWindowSize
.X
= min( condrv_info
.width
, condrv_info
.max_width
);
686 info
->dwMaximumWindowSize
.Y
= min( condrv_info
.height
, condrv_info
.max_height
);
687 info
->wPopupAttributes
= condrv_info
.popup_attr
;
688 info
->bFullscreenSupported
= FALSE
;
689 memcpy( info
->ColorTable
, condrv_info
.color_map
, sizeof(info
->ColorTable
) );
694 /******************************************************************************
695 * GetConsoleTitleW (kernelbase.@)
697 DWORD WINAPI DECLSPEC_HOTPATCH
GetConsoleTitleW( LPWSTR title
, DWORD size
)
701 SERVER_START_REQ( get_console_input_info
)
704 wine_server_set_reply( req
, title
, (size
- 1) * sizeof(WCHAR
) );
705 if (!wine_server_call_err( req
))
707 ret
= wine_server_reply_size(reply
) / sizeof(WCHAR
);
716 /***********************************************************************
717 * GetLargestConsoleWindowSize (kernelbase.@)
719 #if defined(__i386__) && !defined(__MINGW32__) && !defined(_MSC_VER)
720 #undef GetLargestConsoleWindowSize
721 DWORD WINAPI DECLSPEC_HOTPATCH
GetLargestConsoleWindowSize( HANDLE handle
)
727 x
.c
= get_largest_console_window_size( handle
);
733 COORD WINAPI DECLSPEC_HOTPATCH
GetLargestConsoleWindowSize( HANDLE handle
)
735 return get_largest_console_window_size( handle
);
738 #endif /* !defined(__i386__) */
741 /***********************************************************************
742 * GetNumberOfConsoleInputEvents (kernelbase.@)
744 BOOL WINAPI DECLSPEC_HOTPATCH
GetNumberOfConsoleInputEvents( HANDLE handle
, DWORD
*count
)
746 struct condrv_input_info info
;
747 if (!console_ioctl( handle
, IOCTL_CONDRV_GET_INPUT_INFO
, NULL
, 0, &info
, sizeof(info
), NULL
))
749 *count
= info
.input_count
;
754 /***********************************************************************
755 * PeekConsoleInputA (kernelbase.@)
757 BOOL WINAPI DECLSPEC_HOTPATCH
PeekConsoleInputA( HANDLE handle
, INPUT_RECORD
*buffer
,
758 DWORD length
, DWORD
*count
)
762 if (!PeekConsoleInputW( handle
, buffer
, length
, &read
)) return FALSE
;
763 input_records_WtoA( buffer
, read
);
764 if (count
) *count
= read
;
769 /***********************************************************************
770 * PeekConsoleInputW (kernelbase.@)
772 BOOL WINAPI DECLSPEC_HOTPATCH
PeekConsoleInputW( HANDLE handle
, INPUT_RECORD
*buffer
,
773 DWORD length
, DWORD
*count
)
776 if (!console_ioctl( handle
, IOCTL_CONDRV_PEEK
, NULL
, 0, buffer
, length
* sizeof(*buffer
), &read
))
778 if (count
) *count
= read
/ sizeof(*buffer
);
783 /******************************************************************************
784 * ReadConsoleOutputAttribute (kernelbase.@)
786 BOOL WINAPI DECLSPEC_HOTPATCH
ReadConsoleOutputAttribute( HANDLE handle
, WORD
*attr
, DWORD length
,
787 COORD coord
, DWORD
*count
)
789 struct condrv_output_params params
;
792 TRACE( "(%p,%p,%d,%dx%d,%p)\n", handle
, attr
, length
, coord
.X
, coord
.Y
, count
);
796 SetLastError( ERROR_INVALID_ACCESS
);
800 params
.mode
= CHAR_INFO_MODE_ATTR
;
804 ret
= console_ioctl( handle
, IOCTL_CONDRV_READ_OUTPUT
, ¶ms
, sizeof(params
),
805 attr
, length
* sizeof(*attr
), count
);
806 *count
/= sizeof(*attr
);
811 /******************************************************************************
812 * ReadConsoleOutputCharacterA (kernelbase.@)
814 BOOL WINAPI DECLSPEC_HOTPATCH
ReadConsoleOutputCharacterA( HANDLE handle
, LPSTR buffer
, DWORD length
,
815 COORD coord
, DWORD
*count
)
823 SetLastError( ERROR_INVALID_ACCESS
);
828 if (!(wptr
= HeapAlloc( GetProcessHeap(), 0, length
* sizeof(WCHAR
) )))
830 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
833 if ((ret
= ReadConsoleOutputCharacterW( handle
, wptr
, length
, coord
, &read
)))
835 read
= WideCharToMultiByte( GetConsoleOutputCP(), 0, wptr
, read
, buffer
, length
, NULL
, NULL
);
838 HeapFree( GetProcessHeap(), 0, wptr
);
843 /******************************************************************************
844 * ReadConsoleOutputCharacterW (kernelbase.@)
846 BOOL WINAPI DECLSPEC_HOTPATCH
ReadConsoleOutputCharacterW( HANDLE handle
, LPWSTR buffer
, DWORD length
,
847 COORD coord
, DWORD
*count
)
849 struct condrv_output_params params
;
852 TRACE( "(%p,%p,%d,%dx%d,%p)\n", handle
, buffer
, length
, coord
.X
, coord
.Y
, count
);
856 SetLastError( ERROR_INVALID_ACCESS
);
860 params
.mode
= CHAR_INFO_MODE_TEXT
;
864 ret
= console_ioctl( handle
, IOCTL_CONDRV_READ_OUTPUT
, ¶ms
, sizeof(params
), buffer
,
865 length
* sizeof(*buffer
), count
);
866 *count
/= sizeof(*buffer
);
871 /******************************************************************************
872 * ReadConsoleOutputA (kernelbase.@)
874 BOOL WINAPI DECLSPEC_HOTPATCH
ReadConsoleOutputA( HANDLE handle
, CHAR_INFO
*buffer
, COORD size
,
875 COORD coord
, SMALL_RECT
*region
)
880 ret
= ReadConsoleOutputW( handle
, buffer
, size
, coord
, region
);
881 if (ret
&& region
->Right
>= region
->Left
)
883 UINT cp
= GetConsoleOutputCP();
884 for (y
= 0; y
<= region
->Bottom
- region
->Top
; y
++)
885 char_info_WtoA( cp
, &buffer
[(coord
.Y
+ y
) * size
.X
+ coord
.X
], region
->Right
- region
->Left
+ 1 );
891 /******************************************************************************
892 * ReadConsoleOutputW (kernelbase.@)
894 BOOL WINAPI DECLSPEC_HOTPATCH
ReadConsoleOutputW( HANDLE handle
, CHAR_INFO
*buffer
, COORD size
,
895 COORD coord
, SMALL_RECT
*region
)
897 int width
, height
, y
;
900 width
= min( region
->Right
- region
->Left
+ 1, size
.X
- coord
.X
);
901 height
= min( region
->Bottom
- region
->Top
+ 1, size
.Y
- coord
.Y
);
903 if (width
> 0 && height
> 0)
905 for (y
= 0; y
< height
; y
++)
907 SERVER_START_REQ( read_console_output
)
909 req
->handle
= console_handle_unmap( handle
);
910 req
->x
= region
->Left
;
911 req
->y
= region
->Top
+ y
;
912 req
->mode
= CHAR_INFO_MODE_TEXTATTR
;
914 wine_server_set_reply( req
, &buffer
[(y
+coord
.Y
) * size
.X
+ coord
.X
],
915 width
* sizeof(CHAR_INFO
) );
916 if ((ret
= !wine_server_call_err( req
)))
918 width
= min( width
, reply
->width
- region
->Left
);
919 height
= min( height
, reply
->height
- region
->Top
);
926 region
->Bottom
= region
->Top
+ height
- 1;
927 region
->Right
= region
->Left
+ width
- 1;
932 /******************************************************************************
933 * ScrollConsoleScreenBufferA (kernelbase.@)
935 BOOL WINAPI DECLSPEC_HOTPATCH
ScrollConsoleScreenBufferA( HANDLE handle
, SMALL_RECT
*scroll
,
936 SMALL_RECT
*clip
, COORD origin
, CHAR_INFO
*fill
)
940 ciW
.Attributes
= fill
->Attributes
;
941 MultiByteToWideChar( GetConsoleOutputCP(), 0, &fill
->Char
.AsciiChar
, 1, &ciW
.Char
.UnicodeChar
, 1 );
943 return ScrollConsoleScreenBufferW( handle
, scroll
, clip
, origin
, &ciW
);
947 /******************************************************************************
948 * ScrollConsoleScreenBufferW (kernelbase.@)
950 BOOL WINAPI DECLSPEC_HOTPATCH
ScrollConsoleScreenBufferW( HANDLE handle
, SMALL_RECT
*scroll
,
951 SMALL_RECT
*clip_rect
, COORD origin
,
954 CONSOLE_SCREEN_BUFFER_INFO info
;
955 SMALL_RECT dst
, clip
;
956 int i
, j
, start
= -1;
962 TRACE( "(%p,(%d,%d-%d,%d),(%d,%d-%d,%d),%d-%d,%p)\n", handle
,
963 scroll
->Left
, scroll
->Top
, scroll
->Right
, scroll
->Bottom
,
964 clip_rect
->Left
, clip_rect
->Top
, clip_rect
->Right
, clip_rect
->Bottom
,
965 origin
.X
, origin
.Y
, fill
);
967 TRACE("(%p,(%d,%d-%d,%d),(nil),%d-%d,%p)\n", handle
,
968 scroll
->Left
, scroll
->Top
, scroll
->Right
, scroll
->Bottom
,
969 origin
.X
, origin
.Y
, fill
);
971 if (!GetConsoleScreenBufferInfo( handle
, &info
)) return FALSE
;
973 src
.X
= scroll
->Left
;
976 /* step 1: get dst rect */
979 dst
.Right
= dst
.Left
+ (scroll
->Right
- scroll
->Left
);
980 dst
.Bottom
= dst
.Top
+ (scroll
->Bottom
- scroll
->Top
);
982 /* step 2a: compute the final clip rect (optional passed clip and screen buffer limits */
985 clip
.Left
= max(0, clip_rect
->Left
);
986 clip
.Right
= min(info
.dwSize
.X
- 1, clip_rect
->Right
);
987 clip
.Top
= max(0, clip_rect
->Top
);
988 clip
.Bottom
= min(info
.dwSize
.Y
- 1, clip_rect
->Bottom
);
993 clip
.Right
= info
.dwSize
.X
- 1;
995 clip
.Bottom
= info
.dwSize
.Y
- 1;
997 if (clip
.Left
> clip
.Right
|| clip
.Top
> clip
.Bottom
) return FALSE
;
999 /* step 2b: clip dst rect */
1000 if (dst
.Left
< clip
.Left
) {src
.X
+= clip
.Left
- dst
.Left
; dst
.Left
= clip
.Left
;}
1001 if (dst
.Top
< clip
.Top
) {src
.Y
+= clip
.Top
- dst
.Top
; dst
.Top
= clip
.Top
;}
1002 if (dst
.Right
> clip
.Right
) dst
.Right
= clip
.Right
;
1003 if (dst
.Bottom
> clip
.Bottom
) dst
.Bottom
= clip
.Bottom
;
1005 /* step 3: transfer the bits */
1006 SERVER_START_REQ( move_console_output
)
1008 req
->handle
= console_handle_unmap( handle
);
1011 req
->x_dst
= dst
.Left
;
1012 req
->y_dst
= dst
.Top
;
1013 req
->w
= dst
.Right
- dst
.Left
+ 1;
1014 req
->h
= dst
.Bottom
- dst
.Top
+ 1;
1015 ret
= !wine_server_call_err( req
);
1019 if (!ret
) return FALSE
;
1021 /* step 4: clean out the exposed part */
1023 /* have to write cell [i,j] if it is not in dst rect (because it has already
1024 * been written to by the scroll) and is in clip (we shall not write
1027 for (j
= max(scroll
->Top
, clip
.Top
); j
<= min(scroll
->Bottom
, clip
.Bottom
); j
++)
1029 inside
= dst
.Top
<= j
&& j
<= dst
.Bottom
;
1031 for (i
= max(scroll
->Left
, clip
.Left
); i
<= min(scroll
->Right
, clip
.Right
); i
++)
1033 if (inside
&& dst
.Left
<= i
&& i
<= dst
.Right
)
1037 fill_console_output( handle
, start
, j
, i
- start
, fill
);
1043 if (start
== -1) start
= i
;
1046 if (start
!= -1) fill_console_output( handle
, start
, j
, i
- start
, fill
);
1053 /******************************************************************************
1054 * SetConsoleActiveScreenBuffer (kernelbase.@)
1056 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleActiveScreenBuffer( HANDLE handle
)
1058 TRACE( "(%p)\n", handle
);
1059 return console_ioctl( handle
, IOCTL_CONDRV_ACTIVATE
, NULL
, 0, NULL
, 0, NULL
);
1063 /******************************************************************************
1064 * SetConsoleCP (kernelbase.@)
1066 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleCP( UINT cp
)
1070 if (!IsValidCodePage( cp
))
1072 SetLastError( ERROR_INVALID_PARAMETER
);
1075 SERVER_START_REQ( set_console_input_info
)
1078 req
->mask
= SET_CONSOLE_INPUT_INFO_INPUT_CODEPAGE
;
1080 ret
= !wine_server_call_err( req
);
1087 /******************************************************************************
1088 * SetConsoleCtrlHandler (kernelbase.@)
1090 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleCtrlHandler( PHANDLER_ROUTINE func
, BOOL add
)
1092 struct ctrl_handler
*handler
;
1095 TRACE( "(%p,%d)\n", func
, add
);
1097 RtlEnterCriticalSection( &console_section
);
1101 if (add
) NtCurrentTeb()->Peb
->ProcessParameters
->ConsoleFlags
|= 1;
1102 else NtCurrentTeb()->Peb
->ProcessParameters
->ConsoleFlags
&= ~1;
1107 if ((handler
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*handler
) )))
1109 handler
->func
= func
;
1110 handler
->next
= ctrl_handlers
;
1111 ctrl_handlers
= handler
;
1117 struct ctrl_handler
**p_handler
;
1119 for (p_handler
= &ctrl_handlers
; *p_handler
; p_handler
= &(*p_handler
)->next
)
1121 if ((*p_handler
)->func
== func
) break;
1123 if (*p_handler
&& *p_handler
!= &default_handler
)
1125 handler
= *p_handler
;
1126 *p_handler
= handler
->next
;
1127 RtlFreeHeap( GetProcessHeap(), 0, handler
);
1130 else SetLastError( ERROR_INVALID_PARAMETER
);
1133 RtlLeaveCriticalSection( &console_section
);
1138 /******************************************************************************
1139 * SetConsoleCursorInfo (kernelbase.@)
1141 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleCursorInfo( HANDLE handle
, CONSOLE_CURSOR_INFO
*info
)
1143 struct condrv_output_info_params params
= { SET_CONSOLE_OUTPUT_INFO_CURSOR_GEOM
};
1145 TRACE( "(%p,%d,%d)\n", handle
, info
->dwSize
, info
->bVisible
);
1147 params
.info
.cursor_size
= info
->dwSize
;
1148 params
.info
.cursor_visible
= info
->bVisible
;
1149 return console_ioctl( handle
, IOCTL_CONDRV_SET_OUTPUT_INFO
, ¶ms
, sizeof(params
),
1154 /******************************************************************************
1155 * SetConsoleCursorPosition (kernelbase.@)
1157 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleCursorPosition( HANDLE handle
, COORD pos
)
1159 struct condrv_output_info_params params
= { SET_CONSOLE_OUTPUT_INFO_CURSOR_POS
};
1160 CONSOLE_SCREEN_BUFFER_INFO info
;
1161 int w
, h
, do_move
= 0;
1163 TRACE( "%p %d %d\n", handle
, pos
.X
, pos
.Y
);
1165 params
.info
.cursor_x
= pos
.X
;
1166 params
.info
.cursor_y
= pos
.Y
;
1167 if (!console_ioctl( handle
, IOCTL_CONDRV_SET_OUTPUT_INFO
, ¶ms
, sizeof(params
), NULL
, 0, NULL
))
1170 if (!GetConsoleScreenBufferInfo( handle
, &info
)) return FALSE
;
1172 /* if cursor is no longer visible, scroll the visible window... */
1173 w
= info
.srWindow
.Right
- info
.srWindow
.Left
+ 1;
1174 h
= info
.srWindow
.Bottom
- info
.srWindow
.Top
+ 1;
1175 if (pos
.X
< info
.srWindow
.Left
)
1177 info
.srWindow
.Left
= min(pos
.X
, info
.dwSize
.X
- w
);
1180 else if (pos
.X
> info
.srWindow
.Right
)
1182 info
.srWindow
.Left
= max(pos
.X
, w
) - w
+ 1;
1185 info
.srWindow
.Right
= info
.srWindow
.Left
+ w
- 1;
1187 if (pos
.Y
< info
.srWindow
.Top
)
1189 info
.srWindow
.Top
= min(pos
.Y
, info
.dwSize
.Y
- h
);
1192 else if (pos
.Y
> info
.srWindow
.Bottom
)
1194 info
.srWindow
.Top
= max(pos
.Y
, h
) - h
+ 1;
1197 info
.srWindow
.Bottom
= info
.srWindow
.Top
+ h
- 1;
1199 return !do_move
|| SetConsoleWindowInfo( handle
, TRUE
, &info
.srWindow
);
1203 /******************************************************************************
1204 * SetConsoleInputExeNameA (kernelbase.@)
1206 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleInputExeNameA( LPCSTR name
)
1208 if (!name
|| !name
[0])
1210 SetLastError( ERROR_INVALID_PARAMETER
);
1213 RtlEnterCriticalSection( &console_section
);
1214 MultiByteToWideChar( CP_ACP
, 0, name
, -1, input_exe
, ARRAY_SIZE(input_exe
) );
1215 RtlLeaveCriticalSection( &console_section
);
1220 /******************************************************************************
1221 * SetConsoleInputExeNameW (kernelbase.@)
1223 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleInputExeNameW( LPCWSTR name
)
1225 if (!name
|| !name
[0])
1227 SetLastError( ERROR_INVALID_PARAMETER
);
1230 RtlEnterCriticalSection( &console_section
);
1231 lstrcpynW( input_exe
, name
, ARRAY_SIZE(input_exe
) );
1232 RtlLeaveCriticalSection( &console_section
);
1237 /******************************************************************************
1238 * SetConsoleMode (kernelbase.@)
1240 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleMode( HANDLE handle
, DWORD mode
)
1242 TRACE( "(%p,%x)\n", handle
, mode
);
1243 return console_ioctl( handle
, IOCTL_CONDRV_SET_MODE
, &mode
, sizeof(mode
), NULL
, 0, NULL
);
1247 /******************************************************************************
1248 * SetConsoleOutputCP (kernelbase.@)
1250 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleOutputCP( UINT cp
)
1254 if (!IsValidCodePage( cp
))
1256 SetLastError( ERROR_INVALID_PARAMETER
);
1259 SERVER_START_REQ( set_console_input_info
)
1262 req
->mask
= SET_CONSOLE_INPUT_INFO_OUTPUT_CODEPAGE
;
1263 req
->output_cp
= cp
;
1264 ret
= !wine_server_call_err( req
);
1271 /******************************************************************************
1272 * SetConsoleScreenBufferInfoEx (kernelbase.@)
1274 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleScreenBufferInfoEx( HANDLE handle
,
1275 CONSOLE_SCREEN_BUFFER_INFOEX
*info
)
1277 struct condrv_output_info_params params
=
1278 { SET_CONSOLE_OUTPUT_INFO_CURSOR_POS
| SET_CONSOLE_OUTPUT_INFO_SIZE
|
1279 SET_CONSOLE_OUTPUT_INFO_ATTR
| SET_CONSOLE_OUTPUT_INFO_POPUP_ATTR
|
1280 SET_CONSOLE_OUTPUT_INFO_DISPLAY_WINDOW
| SET_CONSOLE_OUTPUT_INFO_MAX_SIZE
};
1282 TRACE("(%p, %p)\n", handle
, info
);
1284 if (info
->cbSize
!= sizeof(CONSOLE_SCREEN_BUFFER_INFOEX
))
1286 SetLastError(ERROR_INVALID_PARAMETER
);
1290 params
.info
.width
= info
->dwSize
.X
;
1291 params
.info
.height
= info
->dwSize
.Y
;
1292 params
.info
.cursor_x
= info
->dwCursorPosition
.X
;
1293 params
.info
.cursor_y
= info
->dwCursorPosition
.Y
;
1294 params
.info
.attr
= info
->wAttributes
;
1295 params
.info
.win_left
= info
->srWindow
.Left
;
1296 params
.info
.win_top
= info
->srWindow
.Top
;
1297 params
.info
.win_right
= info
->srWindow
.Right
;
1298 params
.info
.win_bottom
= info
->srWindow
.Bottom
;
1299 params
.info
.popup_attr
= info
->wPopupAttributes
;
1300 params
.info
.max_width
= min( info
->dwMaximumWindowSize
.X
, info
->dwSize
.X
);
1301 params
.info
.max_height
= min( info
->dwMaximumWindowSize
.Y
, info
->dwSize
.Y
);
1302 return console_ioctl( handle
, IOCTL_CONDRV_SET_OUTPUT_INFO
, ¶ms
, sizeof(params
), NULL
, 0, NULL
);
1306 /******************************************************************************
1307 * SetConsoleScreenBufferSize (kernelbase.@)
1309 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleScreenBufferSize( HANDLE handle
, COORD size
)
1311 struct condrv_output_info_params params
= { SET_CONSOLE_OUTPUT_INFO_SIZE
};
1313 TRACE( "(%p,(%d,%d))\n", handle
, size
.X
, size
.Y
);
1315 params
.info
.width
= size
.X
;
1316 params
.info
.height
= size
.Y
;
1317 return console_ioctl( handle
, IOCTL_CONDRV_SET_OUTPUT_INFO
, ¶ms
, sizeof(params
), NULL
, 0, NULL
);
1321 /******************************************************************************
1322 * SetConsoleTextAttribute (kernelbase.@)
1324 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleTextAttribute( HANDLE handle
, WORD attr
)
1326 struct condrv_output_info_params params
= { SET_CONSOLE_OUTPUT_INFO_ATTR
};
1328 TRACE( "(%p,%d)\n", handle
, attr
);
1330 params
.info
.attr
= attr
;
1331 return console_ioctl( handle
, IOCTL_CONDRV_SET_OUTPUT_INFO
, ¶ms
, sizeof(params
), NULL
, 0, NULL
);
1335 /******************************************************************************
1336 * SetConsoleTitleW (kernelbase.@)
1338 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleTitleW( LPCWSTR title
)
1342 TRACE( "%s\n", debugstr_w( title
));
1343 SERVER_START_REQ( set_console_input_info
)
1346 req
->mask
= SET_CONSOLE_INPUT_INFO_TITLE
;
1347 wine_server_add_data( req
, title
, lstrlenW(title
) * sizeof(WCHAR
) );
1348 ret
= !wine_server_call_err( req
);
1355 /******************************************************************************
1356 * SetConsoleWindowInfo (kernelbase.@)
1358 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleWindowInfo( HANDLE handle
, BOOL absolute
, SMALL_RECT
*window
)
1360 struct condrv_output_info_params params
= { SET_CONSOLE_OUTPUT_INFO_DISPLAY_WINDOW
};
1361 SMALL_RECT rect
= *window
;
1363 TRACE( "(%p,%d,(%d,%d-%d,%d))\n", handle
, absolute
, rect
.Left
, rect
.Top
, rect
.Right
, rect
.Bottom
);
1367 CONSOLE_SCREEN_BUFFER_INFO info
;
1369 if (!GetConsoleScreenBufferInfo( handle
, &info
)) return FALSE
;
1370 rect
.Left
+= info
.srWindow
.Left
;
1371 rect
.Top
+= info
.srWindow
.Top
;
1372 rect
.Right
+= info
.srWindow
.Right
;
1373 rect
.Bottom
+= info
.srWindow
.Bottom
;
1376 params
.info
.win_left
= rect
.Left
;
1377 params
.info
.win_top
= rect
.Top
;
1378 params
.info
.win_right
= rect
.Right
;
1379 params
.info
.win_bottom
= rect
.Bottom
;
1380 return console_ioctl( handle
, IOCTL_CONDRV_SET_OUTPUT_INFO
, ¶ms
, sizeof(params
), NULL
, 0, NULL
);
1384 /******************************************************************************
1385 * WriteConsoleInputA (kernelbase.@)
1387 BOOL WINAPI DECLSPEC_HOTPATCH
WriteConsoleInputA( HANDLE handle
, const INPUT_RECORD
*buffer
,
1388 DWORD count
, DWORD
*written
)
1390 INPUT_RECORD
*recW
= NULL
;
1397 SetLastError( ERROR_INVALID_ACCESS
);
1400 if (!(recW
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(*recW
) )))
1402 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1405 memcpy( recW
, buffer
, count
* sizeof(*recW
) );
1406 input_records_AtoW( recW
, count
);
1408 ret
= WriteConsoleInputW( handle
, recW
, count
, written
);
1409 HeapFree( GetProcessHeap(), 0, recW
);
1414 /******************************************************************************
1415 * WriteConsoleInputW (kernelbase.@)
1417 BOOL WINAPI DECLSPEC_HOTPATCH
WriteConsoleInputW( HANDLE handle
, const INPUT_RECORD
*buffer
,
1418 DWORD count
, DWORD
*written
)
1420 TRACE( "(%p,%p,%d,%p)\n", handle
, buffer
, count
, written
);
1422 if (count
> 0 && !buffer
)
1424 SetLastError( ERROR_INVALID_ACCESS
);
1428 if (!DeviceIoControl( handle
, IOCTL_CONDRV_WRITE_INPUT
, (void *)buffer
, count
* sizeof(*buffer
), NULL
, 0, NULL
, NULL
))
1433 SetLastError( ERROR_INVALID_ACCESS
);
1441 /***********************************************************************
1442 * WriteConsoleOutputA (kernelbase.@)
1444 BOOL WINAPI DECLSPEC_HOTPATCH
WriteConsoleOutputA( HANDLE handle
, const CHAR_INFO
*buffer
,
1445 COORD size
, COORD coord
, SMALL_RECT
*region
)
1449 COORD new_size
, new_coord
;
1452 new_size
.X
= min( region
->Right
- region
->Left
+ 1, size
.X
- coord
.X
);
1453 new_size
.Y
= min( region
->Bottom
- region
->Top
+ 1, size
.Y
- coord
.Y
);
1455 if (new_size
.X
<= 0 || new_size
.Y
<= 0)
1457 region
->Bottom
= region
->Top
+ new_size
.Y
- 1;
1458 region
->Right
= region
->Left
+ new_size
.X
- 1;
1462 /* only copy the useful rectangle */
1463 if (!(ciW
= HeapAlloc( GetProcessHeap(), 0, sizeof(CHAR_INFO
) * new_size
.X
* new_size
.Y
)))
1465 for (y
= 0; y
< new_size
.Y
; y
++)
1466 memcpy( &ciW
[y
* new_size
.X
], &buffer
[(y
+ coord
.Y
) * size
.X
+ coord
.X
],
1467 new_size
.X
* sizeof(CHAR_INFO
) );
1468 char_info_AtoW( ciW
, new_size
.X
* new_size
.Y
);
1469 new_coord
.X
= new_coord
.Y
= 0;
1470 ret
= WriteConsoleOutputW( handle
, ciW
, new_size
, new_coord
, region
);
1471 HeapFree( GetProcessHeap(), 0, ciW
);
1476 /***********************************************************************
1477 * WriteConsoleOutputW (kernelbase.@)
1479 BOOL WINAPI DECLSPEC_HOTPATCH
WriteConsoleOutputW( HANDLE handle
, const CHAR_INFO
*buffer
,
1480 COORD size
, COORD coord
, SMALL_RECT
*region
)
1482 struct condrv_output_params
*params
;
1483 unsigned int width
, height
, y
;
1487 TRACE( "(%p,%p,(%d,%d),(%d,%d),(%d,%dx%d,%d)\n",
1488 handle
, buffer
, size
.X
, size
.Y
, coord
.X
, coord
.Y
,
1489 region
->Left
, region
->Top
, region
->Right
, region
->Bottom
);
1491 if (region
->Left
> region
->Right
|| region
->Top
> region
->Bottom
|| size
.X
<= coord
.X
|| size
.Y
<= coord
.Y
)
1493 SetLastError( ERROR_INVALID_PARAMETER
);
1497 width
= min( region
->Right
- region
->Left
+ 1, size
.X
- coord
.X
);
1498 height
= min( region
->Bottom
- region
->Top
+ 1, size
.Y
- coord
.Y
);
1499 region
->Right
= region
->Left
+ width
- 1;
1500 region
->Bottom
= region
->Top
+ height
- 1;
1502 params_size
= sizeof(*params
) + width
* height
* sizeof(*buffer
);
1503 if (!(params
= HeapAlloc( GetProcessHeap(), 0, params_size
)))
1505 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1509 params
->mode
= CHAR_INFO_MODE_TEXTATTR
;
1510 params
->x
= region
->Left
;
1511 params
->y
= region
->Top
;
1512 params
->width
= width
;
1514 for (y
= 0; y
< height
; y
++)
1515 memcpy( &((CHAR_INFO
*)(params
+ 1))[y
* width
], &buffer
[(y
+ coord
.Y
) * size
.X
+ coord
.X
], width
* sizeof(CHAR_INFO
) );
1517 ret
= console_ioctl( handle
, IOCTL_CONDRV_WRITE_OUTPUT
, params
, params_size
, region
, sizeof(*region
), NULL
);
1518 HeapFree( GetProcessHeap(), 0, params
);
1523 /******************************************************************************
1524 * WriteConsoleOutputAttribute (kernelbase.@)
1526 BOOL WINAPI DECLSPEC_HOTPATCH
WriteConsoleOutputAttribute( HANDLE handle
, const WORD
*attr
, DWORD length
,
1527 COORD coord
, DWORD
*written
)
1529 struct condrv_output_params
*params
;
1533 TRACE( "(%p,%p,%d,%dx%d,%p)\n", handle
, attr
, length
, coord
.X
, coord
.Y
, written
);
1535 if ((length
> 0 && !attr
) || !written
)
1537 SetLastError( ERROR_INVALID_ACCESS
);
1542 size
= sizeof(*params
) + length
* sizeof(WORD
);
1543 if (!(params
= HeapAlloc( GetProcessHeap(), 0, size
))) return FALSE
;
1544 params
->mode
= CHAR_INFO_MODE_ATTR
;
1545 params
->x
= coord
.X
;
1546 params
->y
= coord
.Y
;
1548 memcpy( params
+ 1, attr
, length
* sizeof(*attr
) );
1549 ret
= console_ioctl( handle
, IOCTL_CONDRV_WRITE_OUTPUT
, params
, size
, written
, sizeof(*written
), NULL
);
1550 HeapFree( GetProcessHeap(), 0, params
);
1555 /******************************************************************************
1556 * WriteConsoleOutputCharacterA (kernelbase.@)
1558 BOOL WINAPI DECLSPEC_HOTPATCH
WriteConsoleOutputCharacterA( HANDLE handle
, LPCSTR str
, DWORD length
,
1559 COORD coord
, DWORD
*written
)
1565 TRACE( "(%p,%s,%d,%dx%d,%p)\n", handle
, debugstr_an(str
, length
), length
, coord
.X
, coord
.Y
, written
);
1569 UINT cp
= GetConsoleOutputCP();
1572 SetLastError( ERROR_INVALID_ACCESS
);
1575 lenW
= MultiByteToWideChar( cp
, 0, str
, length
, NULL
, 0 );
1577 if (!(strW
= HeapAlloc( GetProcessHeap(), 0, lenW
* sizeof(WCHAR
) )))
1579 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1582 MultiByteToWideChar( cp
, 0, str
, length
, strW
, lenW
);
1584 ret
= WriteConsoleOutputCharacterW( handle
, strW
, lenW
, coord
, written
);
1585 HeapFree( GetProcessHeap(), 0, strW
);
1590 /******************************************************************************
1591 * WriteConsoleOutputCharacterW (kernelbase.@)
1593 BOOL WINAPI DECLSPEC_HOTPATCH
WriteConsoleOutputCharacterW( HANDLE handle
, LPCWSTR str
, DWORD length
,
1594 COORD coord
, DWORD
*written
)
1596 struct condrv_output_params
*params
;
1600 TRACE( "(%p,%s,%d,%dx%d,%p)\n", handle
, debugstr_wn(str
, length
), length
, coord
.X
, coord
.Y
, written
);
1602 if ((length
> 0 && !str
) || !written
)
1604 SetLastError( ERROR_INVALID_ACCESS
);
1609 size
= sizeof(*params
) + length
* sizeof(WCHAR
);
1610 if (!(params
= HeapAlloc( GetProcessHeap(), 0, size
))) return FALSE
;
1611 params
->mode
= CHAR_INFO_MODE_TEXT
;
1612 params
->x
= coord
.X
;
1613 params
->y
= coord
.Y
;
1615 memcpy( params
+ 1, str
, length
* sizeof(*str
) );
1616 ret
= console_ioctl( handle
, IOCTL_CONDRV_WRITE_OUTPUT
, params
, size
, written
, sizeof(*written
), NULL
);
1617 HeapFree( GetProcessHeap(), 0, params
);