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
10 * Copyright 2020 Jacek Caban for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #define NONAMELESSUNION
34 #define WIN32_NO_STATUS
40 #include "wine/condrv.h"
41 #include "wine/server.h"
42 #include "wine/exception.h"
43 #include "wine/debug.h"
44 #include "kernelbase.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(console
);
49 static CRITICAL_SECTION console_section
;
50 static CRITICAL_SECTION_DEBUG critsect_debug
=
52 0, 0, &console_section
,
53 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
54 0, 0, { (DWORD_PTR
)(__FILE__
": console_section") }
56 static CRITICAL_SECTION console_section
= { &critsect_debug
, -1, 0, 0, 0, 0 };
58 static HANDLE console_connection
;
59 static HANDLE console_wait_event
;
60 static unsigned int console_flags
;
62 #define CONSOLE_INPUT_HANDLE 0x01
63 #define CONSOLE_OUTPUT_HANDLE 0x02
64 #define CONSOLE_ERROR_HANDLE 0x04
66 static WCHAR input_exe
[MAX_PATH
+ 1];
70 PHANDLER_ROUTINE func
;
71 struct ctrl_handler
*next
;
74 static BOOL WINAPI
default_ctrl_handler( DWORD type
)
76 FIXME( "Terminating process %x on event %x\n", GetCurrentProcessId(), type
);
77 RtlExitUserProcess( 0 );
81 static struct ctrl_handler default_handler
= { default_ctrl_handler
, NULL
};
82 static struct ctrl_handler
*ctrl_handlers
= &default_handler
;
84 static BOOL
console_ioctl( HANDLE handle
, DWORD code
, void *in_buff
, DWORD in_count
,
85 void *out_buff
, DWORD out_count
, DWORD
*read
)
90 status
= NtDeviceIoControlFile( handle
, NULL
, NULL
, NULL
, &io
, code
, in_buff
, in_count
,
91 out_buff
, out_count
);
95 if (read
) *read
= io
.Information
;
97 case STATUS_INVALID_PARAMETER
:
100 status
= STATUS_INVALID_HANDLE
;
104 return set_ntstatus( status
);
107 /* map input records to ASCII */
108 static void input_records_WtoA( INPUT_RECORD
*buffer
, int count
)
110 UINT cp
= GetConsoleCP();
114 for (i
= 0; i
< count
; i
++)
116 if (buffer
[i
].EventType
!= KEY_EVENT
) continue;
117 WideCharToMultiByte( cp
, 0, &buffer
[i
].Event
.KeyEvent
.uChar
.UnicodeChar
, 1, &ch
, 1, NULL
, NULL
);
118 buffer
[i
].Event
.KeyEvent
.uChar
.AsciiChar
= ch
;
122 /* map input records to Unicode */
123 static void input_records_AtoW( INPUT_RECORD
*buffer
, int count
)
125 UINT cp
= GetConsoleCP();
129 for (i
= 0; i
< count
; i
++)
131 if (buffer
[i
].EventType
!= KEY_EVENT
) continue;
132 MultiByteToWideChar( cp
, 0, &buffer
[i
].Event
.KeyEvent
.uChar
.AsciiChar
, 1, &ch
, 1 );
133 buffer
[i
].Event
.KeyEvent
.uChar
.UnicodeChar
= ch
;
137 /* map char infos to ASCII */
138 static void char_info_WtoA( UINT cp
, CHAR_INFO
*buffer
, int count
)
144 WideCharToMultiByte( cp
, 0, &buffer
->Char
.UnicodeChar
, 1, &ch
, 1, NULL
, NULL
);
145 buffer
->Char
.AsciiChar
= ch
;
150 /* map char infos to Unicode */
151 static void char_info_AtoW( CHAR_INFO
*buffer
, int count
)
153 UINT cp
= GetConsoleOutputCP();
158 MultiByteToWideChar( cp
, 0, &buffer
->Char
.AsciiChar
, 1, &ch
, 1 );
159 buffer
->Char
.UnicodeChar
= ch
;
164 /* helper function for GetLargestConsoleWindowSize */
165 static COORD
get_largest_console_window_size( HANDLE handle
)
167 struct condrv_output_info info
;
170 if (!console_ioctl( handle
, IOCTL_CONDRV_GET_OUTPUT_INFO
, NULL
, 0, &info
, sizeof(info
), NULL
))
173 c
.X
= info
.max_width
;
174 c
.Y
= info
.max_height
;
175 TRACE( "(%p), returning %dx%d\n", handle
, c
.X
, c
.Y
);
179 static HANDLE
create_console_server( void )
181 OBJECT_ATTRIBUTES attr
= {sizeof(attr
)};
182 UNICODE_STRING string
;
183 IO_STATUS_BLOCK iosb
;
187 RtlInitUnicodeString( &string
, L
"\\Device\\ConDrv\\Server" );
188 attr
.ObjectName
= &string
;
189 attr
.Attributes
= OBJ_INHERIT
;
190 status
= NtCreateFile( &handle
, FILE_WRITE_PROPERTIES
| FILE_READ_PROPERTIES
| SYNCHRONIZE
,
191 &attr
, &iosb
, NULL
, FILE_ATTRIBUTE_NORMAL
, 0, FILE_OPEN
,
192 FILE_NON_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0 );
193 return set_ntstatus( status
) ? handle
: NULL
;
196 static HANDLE
create_console_reference( HANDLE root
)
198 OBJECT_ATTRIBUTES attr
= {sizeof(attr
)};
199 UNICODE_STRING string
;
200 IO_STATUS_BLOCK iosb
;
204 RtlInitUnicodeString( &string
, L
"Reference" );
205 attr
.RootDirectory
= root
;
206 attr
.ObjectName
= &string
;
207 status
= NtCreateFile( &handle
, FILE_READ_DATA
| FILE_WRITE_DATA
| FILE_WRITE_PROPERTIES
|
208 FILE_READ_PROPERTIES
| SYNCHRONIZE
, &attr
, &iosb
, NULL
, FILE_ATTRIBUTE_NORMAL
,
209 0, FILE_OPEN
, FILE_NON_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0 );
210 return set_ntstatus( status
) ? handle
: NULL
;
213 static BOOL
create_console_connection( HANDLE root
)
215 OBJECT_ATTRIBUTES attr
= {sizeof(attr
)};
216 UNICODE_STRING string
;
217 IO_STATUS_BLOCK iosb
;
220 RtlInitUnicodeString( &string
, root
? L
"Connection" : L
"\\Device\\ConDrv\\Connection" );
221 attr
.RootDirectory
= root
;
222 attr
.ObjectName
= &string
;
223 status
= NtCreateFile( &console_connection
, FILE_WRITE_PROPERTIES
| FILE_READ_PROPERTIES
| SYNCHRONIZE
, &attr
,
224 &iosb
, NULL
, FILE_ATTRIBUTE_NORMAL
, 0, FILE_OPEN
, FILE_NON_DIRECTORY_FILE
, NULL
, 0 );
225 return set_ntstatus( status
);
228 static BOOL
init_console_std_handles( BOOL override_all
)
230 HANDLE std_out
= NULL
, std_err
= NULL
, handle
;
231 OBJECT_ATTRIBUTES attr
= {sizeof(attr
)};
232 IO_STATUS_BLOCK iosb
;
236 attr
.ObjectName
= &name
;
237 attr
.Attributes
= OBJ_INHERIT
;
239 if (override_all
|| !GetStdHandle( STD_INPUT_HANDLE
))
241 /* FIXME: Use unbound console handle */
242 RtlInitUnicodeString( &name
, L
"\\Device\\ConDrv\\CurrentIn" );
243 status
= NtCreateFile( &handle
, FILE_READ_DATA
| FILE_WRITE_DATA
| SYNCHRONIZE
| FILE_READ_ATTRIBUTES
|
244 FILE_WRITE_ATTRIBUTES
, &attr
, &iosb
, NULL
, FILE_ATTRIBUTE_NORMAL
,
245 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
, FILE_CREATE
,
246 FILE_NON_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0 );
247 if (!set_ntstatus( status
)) return FALSE
;
248 console_flags
|= CONSOLE_INPUT_HANDLE
;
249 SetStdHandle( STD_INPUT_HANDLE
, console_handle_map( handle
));
254 std_out
= GetStdHandle( STD_OUTPUT_HANDLE
);
255 std_err
= GetStdHandle( STD_ERROR_HANDLE
);
256 if (std_out
&& std_err
) return TRUE
;
259 /* FIXME: Use unbound console handle */
260 RtlInitUnicodeString( &name
, L
"\\Device\\ConDrv\\CurrentOut" );
261 status
= NtCreateFile( &handle
, FILE_READ_DATA
| FILE_WRITE_DATA
| SYNCHRONIZE
| FILE_READ_ATTRIBUTES
|
262 FILE_WRITE_ATTRIBUTES
, &attr
, &iosb
, NULL
, FILE_ATTRIBUTE_NORMAL
,
263 FILE_SHARE_READ
| FILE_SHARE_WRITE
| FILE_SHARE_DELETE
, FILE_CREATE
,
264 FILE_NON_DIRECTORY_FILE
| FILE_SYNCHRONOUS_IO_NONALERT
, NULL
, 0 );
265 if (!set_ntstatus( status
)) return FALSE
;
268 console_flags
|= CONSOLE_OUTPUT_HANDLE
;
269 SetStdHandle( STD_OUTPUT_HANDLE
, console_handle_map( handle
));
274 if (!std_out
&& !DuplicateHandle( GetCurrentProcess(), handle
, GetCurrentProcess(),
275 &handle
, 0, TRUE
, DUPLICATE_SAME_ACCESS
))
277 console_flags
|= CONSOLE_ERROR_HANDLE
;
278 SetStdHandle( STD_ERROR_HANDLE
, console_handle_map( handle
));
284 /******************************************************************
285 * AttachConsole (kernelbase.@)
287 BOOL WINAPI DECLSPEC_HOTPATCH
AttachConsole( DWORD pid
)
291 TRACE( "(%x)\n", pid
);
293 RtlEnterCriticalSection( &console_section
);
295 if (RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
)
297 RtlLeaveCriticalSection( &console_section
);
298 WARN( "console already attached\n" );
299 SetLastError( ERROR_ACCESS_DENIED
);
303 ret
= create_console_connection( NULL
) &&
304 console_ioctl( console_connection
, IOCTL_CONDRV_BIND_PID
, &pid
, sizeof(pid
), NULL
, 0, NULL
);
307 RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
= create_console_reference( console_connection
);
308 if (RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
)
311 GetStartupInfoW( &si
);
312 init_console_std_handles( !(si
.dwFlags
& STARTF_USESTDHANDLES
) );
317 if (!ret
) FreeConsole();
318 RtlLeaveCriticalSection( &console_section
);
323 /******************************************************************
324 * AllocConsole (kernelbase.@)
326 BOOL WINAPI
AllocConsole(void)
328 SECURITY_ATTRIBUTES inheritable_attr
= { sizeof(inheritable_attr
), NULL
, TRUE
};
329 STARTUPINFOW app_si
, console_si
;
330 HANDLE server
, console
= NULL
;
331 WCHAR buffer
[1024], cmd
[256], conhost_path
[MAX_PATH
];
332 PROCESS_INFORMATION pi
;
338 RtlEnterCriticalSection( &console_section
);
340 if (RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
)
342 /* we already have a console opened on this process, don't create a new one */
343 RtlLeaveCriticalSection( &console_section
);
344 SetLastError( ERROR_ACCESS_DENIED
);
348 if (!(server
= create_console_server()) || !(console
= create_console_reference( server
))) goto error
;
350 GetStartupInfoW(&app_si
);
352 memset(&console_si
, 0, sizeof(console_si
));
353 console_si
.cb
= sizeof(console_si
);
354 /* setup a view arguments for wineconsole (it'll use them as default values) */
355 if (app_si
.dwFlags
& STARTF_USECOUNTCHARS
)
357 console_si
.dwFlags
|= STARTF_USECOUNTCHARS
;
358 console_si
.dwXCountChars
= app_si
.dwXCountChars
;
359 console_si
.dwYCountChars
= app_si
.dwYCountChars
;
361 if (app_si
.dwFlags
& STARTF_USEFILLATTRIBUTE
)
363 console_si
.dwFlags
|= STARTF_USEFILLATTRIBUTE
;
364 console_si
.dwFillAttribute
= app_si
.dwFillAttribute
;
366 if (app_si
.dwFlags
& STARTF_USESHOWWINDOW
)
368 console_si
.dwFlags
|= STARTF_USESHOWWINDOW
;
369 console_si
.wShowWindow
= app_si
.wShowWindow
;
372 console_si
.lpTitle
= app_si
.lpTitle
;
373 else if (GetModuleFileNameW(0, buffer
, ARRAY_SIZE(buffer
)))
375 buffer
[ARRAY_SIZE(buffer
) - 1] = 0;
376 console_si
.lpTitle
= buffer
;
379 swprintf( conhost_path
, ARRAY_SIZE(conhost_path
), L
"%s\\conhost.exe", system_dir
);
380 swprintf( cmd
, ARRAY_SIZE(cmd
), L
"\"%s\" --server 0x%x", conhost_path
, condrv_handle( server
));
381 Wow64DisableWow64FsRedirection( &redir
);
382 ret
= CreateProcessW( conhost_path
, cmd
, NULL
, NULL
, TRUE
, DETACHED_PROCESS
, NULL
, NULL
, &console_si
, &pi
);
383 Wow64RevertWow64FsRedirection( redir
);
385 if (!ret
|| !create_console_connection( console
)) goto error
;
386 if (!init_console_std_handles( !(app_si
.dwFlags
& STARTF_USESTDHANDLES
) )) goto error
;
388 RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
= console
;
389 TRACE( "Started wineconsole pid=%08x tid=%08x\n", pi
.dwProcessId
, pi
.dwThreadId
);
391 CloseHandle( server
);
392 RtlLeaveCriticalSection( &console_section
);
393 SetLastError( ERROR_SUCCESS
);
397 ERR("Can't allocate console\n");
401 RtlLeaveCriticalSection( &console_section
);
406 /******************************************************************************
407 * CreateConsoleScreenBuffer (kernelbase.@)
409 HANDLE WINAPI DECLSPEC_HOTPATCH
CreateConsoleScreenBuffer( DWORD access
, DWORD share
,
410 SECURITY_ATTRIBUTES
*sa
, DWORD flags
,
413 OBJECT_ATTRIBUTES attr
= {sizeof(attr
)};
414 IO_STATUS_BLOCK iosb
;
419 TRACE( "(%x,%x,%p,%x,%p)\n", access
, share
, sa
, flags
, data
);
421 if (flags
!= CONSOLE_TEXTMODE_BUFFER
|| data
)
423 SetLastError( ERROR_INVALID_PARAMETER
);
424 return INVALID_HANDLE_VALUE
;
427 RtlInitUnicodeString( &name
, L
"\\Device\\ConDrv\\ScreenBuffer" );
428 attr
.ObjectName
= &name
;
429 attr
.SecurityDescriptor
= sa
? sa
->lpSecurityDescriptor
: NULL
;
430 if (sa
&& sa
->bInheritHandle
) attr
.Attributes
|= OBJ_INHERIT
;
431 status
= NtCreateFile( &handle
, access
, &attr
, &iosb
, NULL
, FILE_ATTRIBUTE_NORMAL
, 0, FILE_OPEN
,
432 FILE_NON_DIRECTORY_FILE
, NULL
, 0 );
433 return set_ntstatus( status
) ? handle
: INVALID_HANDLE_VALUE
;
437 /******************************************************************************
438 * CtrlRoutine (kernelbase.@)
440 DWORD WINAPI
CtrlRoutine( void *arg
)
442 DWORD_PTR event
= (DWORD_PTR
)arg
;
443 struct ctrl_handler
*handler
;
445 if (event
== CTRL_C_EVENT
)
447 BOOL caught_by_dbg
= TRUE
;
448 /* First, try to pass the ctrl-C event to the debugger (if any)
449 * If it continues, there's nothing more to do
450 * Otherwise, we need to send the ctrl-C event to the handlers
454 RaiseException( DBG_CONTROL_C
, 0, 0, NULL
);
458 caught_by_dbg
= FALSE
;
461 if (caught_by_dbg
) return 0;
464 if (NtCurrentTeb()->Peb
->ProcessParameters
->ConsoleFlags
& 1) return 0;
466 RtlEnterCriticalSection( &console_section
);
467 for (handler
= ctrl_handlers
; handler
; handler
= handler
->next
)
469 if (handler
->func( event
)) break;
471 RtlLeaveCriticalSection( &console_section
);
476 static LONG WINAPI
handle_ctrl_c( EXCEPTION_POINTERS
*eptr
)
478 if (eptr
->ExceptionRecord
->ExceptionCode
!= CONTROL_C_EXIT
) return EXCEPTION_CONTINUE_SEARCH
;
479 if (!RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
) return EXCEPTION_CONTINUE_SEARCH
;
481 if (!(NtCurrentTeb()->Peb
->ProcessParameters
->ConsoleFlags
& 1))
483 HANDLE thread
= CreateThread( NULL
, 0, CtrlRoutine
, (void*)CTRL_C_EVENT
, 0, NULL
);
484 if (thread
) CloseHandle( thread
);
486 return EXCEPTION_CONTINUE_EXECUTION
;
490 /******************************************************************************
491 * FillConsoleOutputAttribute (kernelbase.@)
493 BOOL WINAPI DECLSPEC_HOTPATCH
FillConsoleOutputAttribute( HANDLE handle
, WORD attr
, DWORD length
,
494 COORD coord
, DWORD
*written
)
496 struct condrv_fill_output_params params
;
498 TRACE( "(%p,%d,%d,(%dx%d),%p)\n", handle
, attr
, length
, coord
.X
, coord
.Y
, written
);
502 SetLastError( ERROR_INVALID_ACCESS
);
508 params
.mode
= CHAR_INFO_MODE_ATTR
;
511 params
.count
= length
;
515 return console_ioctl( handle
, IOCTL_CONDRV_FILL_OUTPUT
, ¶ms
, sizeof(params
),
516 written
, sizeof(*written
), NULL
);
520 /******************************************************************************
521 * FillConsoleOutputCharacterA (kernelbase.@)
523 BOOL WINAPI DECLSPEC_HOTPATCH
FillConsoleOutputCharacterA( HANDLE handle
, CHAR ch
, DWORD length
,
524 COORD coord
, DWORD
*written
)
528 MultiByteToWideChar( GetConsoleOutputCP(), 0, &ch
, 1, &wch
, 1 );
529 return FillConsoleOutputCharacterW( handle
, wch
, length
, coord
, written
);
533 /******************************************************************************
534 * FillConsoleOutputCharacterW (kernelbase.@)
536 BOOL WINAPI DECLSPEC_HOTPATCH
FillConsoleOutputCharacterW( HANDLE handle
, WCHAR ch
, DWORD length
,
537 COORD coord
, DWORD
*written
)
539 struct condrv_fill_output_params params
;
541 TRACE( "(%p,%s,%d,(%dx%d),%p)\n", handle
, debugstr_wn(&ch
, 1), length
, coord
.X
, coord
.Y
, written
);
545 SetLastError( ERROR_INVALID_ACCESS
);
551 params
.mode
= CHAR_INFO_MODE_TEXT
;
554 params
.count
= length
;
558 return console_ioctl( handle
, IOCTL_CONDRV_FILL_OUTPUT
, ¶ms
, sizeof(params
),
559 written
, sizeof(*written
), NULL
);
562 HANDLE
get_console_wait_handle( HANDLE handle
)
566 SERVER_START_REQ( get_console_wait_event
)
568 req
->handle
= wine_server_obj_handle( console_handle_map( handle
));
569 if (!wine_server_call( req
)) event
= wine_server_ptr_handle( reply
->event
);
574 if (InterlockedCompareExchangePointer( &console_wait_event
, event
, 0 )) NtClose( event
);
575 handle
= console_wait_event
;
581 /***********************************************************************
582 * FreeConsole (kernelbase.@)
584 BOOL WINAPI DECLSPEC_HOTPATCH
FreeConsole(void)
588 RtlEnterCriticalSection( &console_section
);
590 NtClose( console_connection
);
591 console_connection
= NULL
;
593 NtClose( RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
);
594 RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
= NULL
;
596 if (console_flags
& CONSOLE_INPUT_HANDLE
) NtClose( GetStdHandle( STD_INPUT_HANDLE
));
597 if (console_flags
& CONSOLE_OUTPUT_HANDLE
) NtClose( GetStdHandle( STD_OUTPUT_HANDLE
));
598 if (console_flags
& CONSOLE_ERROR_HANDLE
) NtClose( GetStdHandle( STD_ERROR_HANDLE
));
601 if ((event
= InterlockedExchangePointer( &console_wait_event
, NULL
))) NtClose( event
);
603 RtlLeaveCriticalSection( &console_section
);
608 /******************************************************************************
609 * GenerateConsoleCtrlEvent (kernelbase.@)
611 BOOL WINAPI DECLSPEC_HOTPATCH
GenerateConsoleCtrlEvent( DWORD event
, DWORD group
)
613 struct condrv_ctrl_event ctrl_event
;
615 TRACE( "(%d, %x)\n", event
, group
);
617 if (event
!= CTRL_C_EVENT
&& event
!= CTRL_BREAK_EVENT
)
619 ERR( "Invalid event %d for PGID %x\n", event
, group
);
623 ctrl_event
.event
= event
;
624 ctrl_event
.group_id
= group
;
625 return console_ioctl( RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
,
626 IOCTL_CONDRV_CTRL_EVENT
, &ctrl_event
, sizeof(ctrl_event
), NULL
, 0, NULL
);
630 /******************************************************************************
631 * GetConsoleCP (kernelbase.@)
633 UINT WINAPI DECLSPEC_HOTPATCH
GetConsoleCP(void)
635 struct condrv_input_info info
;
637 if (!console_ioctl( RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
,
638 IOCTL_CONDRV_GET_INPUT_INFO
, NULL
, 0, &info
, sizeof(info
), NULL
))
640 return info
.input_cp
;
644 /******************************************************************************
645 * GetConsoleCursorInfo (kernelbase.@)
647 BOOL WINAPI DECLSPEC_HOTPATCH
GetConsoleCursorInfo( HANDLE handle
, CONSOLE_CURSOR_INFO
*info
)
649 struct condrv_output_info condrv_info
;
651 if (!console_ioctl( handle
, IOCTL_CONDRV_GET_OUTPUT_INFO
, NULL
, 0, &condrv_info
, sizeof(condrv_info
), NULL
))
656 SetLastError( ERROR_INVALID_ACCESS
);
660 info
->dwSize
= condrv_info
.cursor_size
;
661 info
->bVisible
= condrv_info
.cursor_visible
;
662 TRACE("(%p) returning (%d,%d)\n", handle
, info
->dwSize
, info
->bVisible
);
667 /***********************************************************************
668 * GetConsoleInputExeNameA (kernelbase.@)
670 BOOL WINAPI DECLSPEC_HOTPATCH
GetConsoleInputExeNameA( DWORD len
, LPSTR buffer
)
672 RtlEnterCriticalSection( &console_section
);
673 if (WideCharToMultiByte( CP_ACP
, 0, input_exe
, -1, NULL
, 0, NULL
, NULL
) <= len
)
674 WideCharToMultiByte( CP_ACP
, 0, input_exe
, -1, buffer
, len
, NULL
, NULL
);
675 else SetLastError(ERROR_BUFFER_OVERFLOW
);
676 RtlLeaveCriticalSection( &console_section
);
681 /***********************************************************************
682 * GetConsoleInputExeNameW (kernelbase.@)
684 BOOL WINAPI DECLSPEC_HOTPATCH
GetConsoleInputExeNameW( DWORD len
, LPWSTR buffer
)
686 RtlEnterCriticalSection( &console_section
);
687 if (len
> lstrlenW(input_exe
)) lstrcpyW( buffer
, input_exe
);
688 else SetLastError( ERROR_BUFFER_OVERFLOW
);
689 RtlLeaveCriticalSection( &console_section
);
694 /***********************************************************************
695 * GetConsoleMode (kernelbase.@)
697 BOOL WINAPI DECLSPEC_HOTPATCH
GetConsoleMode( HANDLE handle
, DWORD
*mode
)
699 return console_ioctl( handle
, IOCTL_CONDRV_GET_MODE
, NULL
, 0, mode
, sizeof(*mode
), NULL
);
703 /***********************************************************************
704 * GetConsoleOutputCP (kernelbase.@)
706 UINT WINAPI DECLSPEC_HOTPATCH
GetConsoleOutputCP(void)
708 struct condrv_input_info info
;
710 if (!console_ioctl( RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
,
711 IOCTL_CONDRV_GET_INPUT_INFO
, NULL
, 0, &info
, sizeof(info
), NULL
))
713 return info
.output_cp
;
717 /***********************************************************************
718 * GetConsoleScreenBufferInfo (kernelbase.@)
720 BOOL WINAPI DECLSPEC_HOTPATCH
GetConsoleScreenBufferInfo( HANDLE handle
, CONSOLE_SCREEN_BUFFER_INFO
*info
)
722 struct condrv_output_info condrv_info
;
724 if (!console_ioctl( handle
, IOCTL_CONDRV_GET_OUTPUT_INFO
, NULL
, 0,
725 &condrv_info
, sizeof(condrv_info
), NULL
))
728 info
->dwSize
.X
= condrv_info
.width
;
729 info
->dwSize
.Y
= condrv_info
.height
;
730 info
->dwCursorPosition
.X
= condrv_info
.cursor_x
;
731 info
->dwCursorPosition
.Y
= condrv_info
.cursor_y
;
732 info
->wAttributes
= condrv_info
.attr
;
733 info
->srWindow
.Left
= condrv_info
.win_left
;
734 info
->srWindow
.Right
= condrv_info
.win_right
;
735 info
->srWindow
.Top
= condrv_info
.win_top
;
736 info
->srWindow
.Bottom
= condrv_info
.win_bottom
;
737 info
->dwMaximumWindowSize
.X
= min(condrv_info
.width
, condrv_info
.max_width
);
738 info
->dwMaximumWindowSize
.Y
= min(condrv_info
.height
, condrv_info
.max_height
);
740 TRACE( "(%p,(%d,%d) (%d,%d) %d (%d,%d-%d,%d) (%d,%d)\n", handle
,
741 info
->dwSize
.X
, info
->dwSize
.Y
, info
->dwCursorPosition
.X
, info
->dwCursorPosition
.Y
,
742 info
->wAttributes
, info
->srWindow
.Left
, info
->srWindow
.Top
, info
->srWindow
.Right
,
743 info
->srWindow
.Bottom
, info
->dwMaximumWindowSize
.X
, info
->dwMaximumWindowSize
.Y
);
748 /***********************************************************************
749 * GetConsoleScreenBufferInfoEx (kernelbase.@)
751 BOOL WINAPI DECLSPEC_HOTPATCH
GetConsoleScreenBufferInfoEx( HANDLE handle
,
752 CONSOLE_SCREEN_BUFFER_INFOEX
*info
)
754 struct condrv_output_info condrv_info
;
756 if (info
->cbSize
!= sizeof(CONSOLE_SCREEN_BUFFER_INFOEX
))
758 SetLastError( ERROR_INVALID_PARAMETER
);
762 if (!console_ioctl( handle
, IOCTL_CONDRV_GET_OUTPUT_INFO
, NULL
, 0, &condrv_info
,
763 sizeof(condrv_info
), NULL
))
766 info
->dwSize
.X
= condrv_info
.width
;
767 info
->dwSize
.Y
= condrv_info
.height
;
768 info
->dwCursorPosition
.X
= condrv_info
.cursor_x
;
769 info
->dwCursorPosition
.Y
= condrv_info
.cursor_y
;
770 info
->wAttributes
= condrv_info
.attr
;
771 info
->srWindow
.Left
= condrv_info
.win_left
;
772 info
->srWindow
.Top
= condrv_info
.win_top
;
773 info
->srWindow
.Right
= condrv_info
.win_right
;
774 info
->srWindow
.Bottom
= condrv_info
.win_bottom
;
775 info
->dwMaximumWindowSize
.X
= min( condrv_info
.width
, condrv_info
.max_width
);
776 info
->dwMaximumWindowSize
.Y
= min( condrv_info
.height
, condrv_info
.max_height
);
777 info
->wPopupAttributes
= condrv_info
.popup_attr
;
778 info
->bFullscreenSupported
= FALSE
;
779 memcpy( info
->ColorTable
, condrv_info
.color_map
, sizeof(info
->ColorTable
) );
784 /******************************************************************************
785 * GetConsoleTitleW (kernelbase.@)
787 DWORD WINAPI DECLSPEC_HOTPATCH
GetConsoleTitleW( LPWSTR title
, DWORD size
)
791 if (!console_ioctl( RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
, IOCTL_CONDRV_GET_TITLE
,
792 NULL
, 0, title
, (size
- 1) * sizeof(WCHAR
), &size
))
795 size
/= sizeof(WCHAR
);
801 /***********************************************************************
802 * GetLargestConsoleWindowSize (kernelbase.@)
804 #if defined(__i386__) && !defined(__MINGW32__) && !defined(_MSC_VER)
805 #undef GetLargestConsoleWindowSize
806 DWORD WINAPI DECLSPEC_HOTPATCH
GetLargestConsoleWindowSize( HANDLE handle
)
812 x
.c
= get_largest_console_window_size( handle
);
818 COORD WINAPI DECLSPEC_HOTPATCH
GetLargestConsoleWindowSize( HANDLE handle
)
820 return get_largest_console_window_size( handle
);
823 #endif /* !defined(__i386__) */
826 /***********************************************************************
827 * GetNumberOfConsoleInputEvents (kernelbase.@)
829 BOOL WINAPI DECLSPEC_HOTPATCH
GetNumberOfConsoleInputEvents( HANDLE handle
, DWORD
*count
)
831 struct condrv_input_info info
;
832 if (!console_ioctl( handle
, IOCTL_CONDRV_GET_INPUT_INFO
, NULL
, 0, &info
, sizeof(info
), NULL
))
834 *count
= info
.input_count
;
839 /***********************************************************************
840 * PeekConsoleInputA (kernelbase.@)
842 BOOL WINAPI DECLSPEC_HOTPATCH
PeekConsoleInputA( HANDLE handle
, INPUT_RECORD
*buffer
,
843 DWORD length
, DWORD
*count
)
847 if (!PeekConsoleInputW( handle
, buffer
, length
, &read
)) return FALSE
;
848 input_records_WtoA( buffer
, read
);
849 if (count
) *count
= read
;
854 /***********************************************************************
855 * PeekConsoleInputW (kernelbase.@)
857 BOOL WINAPI DECLSPEC_HOTPATCH
PeekConsoleInputW( HANDLE handle
, INPUT_RECORD
*buffer
,
858 DWORD length
, DWORD
*count
)
861 if (!console_ioctl( handle
, IOCTL_CONDRV_PEEK
, NULL
, 0, buffer
, length
* sizeof(*buffer
), &read
))
863 if (count
) *count
= read
/ sizeof(*buffer
);
868 /******************************************************************************
869 * ReadConsoleOutputAttribute (kernelbase.@)
871 BOOL WINAPI DECLSPEC_HOTPATCH
ReadConsoleOutputAttribute( HANDLE handle
, WORD
*attr
, DWORD length
,
872 COORD coord
, DWORD
*count
)
874 struct condrv_output_params params
;
877 TRACE( "(%p,%p,%d,%dx%d,%p)\n", handle
, attr
, length
, coord
.X
, coord
.Y
, count
);
881 SetLastError( ERROR_INVALID_ACCESS
);
885 params
.mode
= CHAR_INFO_MODE_ATTR
;
889 ret
= console_ioctl( handle
, IOCTL_CONDRV_READ_OUTPUT
, ¶ms
, sizeof(params
),
890 attr
, length
* sizeof(*attr
), count
);
891 *count
/= sizeof(*attr
);
896 /******************************************************************************
897 * ReadConsoleOutputCharacterA (kernelbase.@)
899 BOOL WINAPI DECLSPEC_HOTPATCH
ReadConsoleOutputCharacterA( HANDLE handle
, LPSTR buffer
, DWORD length
,
900 COORD coord
, DWORD
*count
)
908 SetLastError( ERROR_INVALID_ACCESS
);
913 if (!(wptr
= HeapAlloc( GetProcessHeap(), 0, length
* sizeof(WCHAR
) )))
915 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
918 if ((ret
= ReadConsoleOutputCharacterW( handle
, wptr
, length
, coord
, &read
)))
920 read
= WideCharToMultiByte( GetConsoleOutputCP(), 0, wptr
, read
, buffer
, length
, NULL
, NULL
);
923 HeapFree( GetProcessHeap(), 0, wptr
);
928 /******************************************************************************
929 * ReadConsoleOutputCharacterW (kernelbase.@)
931 BOOL WINAPI DECLSPEC_HOTPATCH
ReadConsoleOutputCharacterW( HANDLE handle
, LPWSTR buffer
, DWORD length
,
932 COORD coord
, DWORD
*count
)
934 struct condrv_output_params params
;
937 TRACE( "(%p,%p,%d,%dx%d,%p)\n", handle
, buffer
, length
, coord
.X
, coord
.Y
, count
);
941 SetLastError( ERROR_INVALID_ACCESS
);
945 params
.mode
= CHAR_INFO_MODE_TEXT
;
949 ret
= console_ioctl( handle
, IOCTL_CONDRV_READ_OUTPUT
, ¶ms
, sizeof(params
), buffer
,
950 length
* sizeof(*buffer
), count
);
951 *count
/= sizeof(*buffer
);
956 /******************************************************************************
957 * ReadConsoleOutputA (kernelbase.@)
959 BOOL WINAPI DECLSPEC_HOTPATCH
ReadConsoleOutputA( HANDLE handle
, CHAR_INFO
*buffer
, COORD size
,
960 COORD coord
, SMALL_RECT
*region
)
965 ret
= ReadConsoleOutputW( handle
, buffer
, size
, coord
, region
);
966 if (ret
&& region
->Right
>= region
->Left
)
968 UINT cp
= GetConsoleOutputCP();
969 for (y
= 0; y
<= region
->Bottom
- region
->Top
; y
++)
970 char_info_WtoA( cp
, &buffer
[(coord
.Y
+ y
) * size
.X
+ coord
.X
], region
->Right
- region
->Left
+ 1 );
976 /******************************************************************************
977 * ReadConsoleOutputW (kernelbase.@)
979 BOOL WINAPI DECLSPEC_HOTPATCH
ReadConsoleOutputW( HANDLE handle
, CHAR_INFO
*buffer
, COORD size
,
980 COORD coord
, SMALL_RECT
*region
)
982 struct condrv_output_params params
;
983 unsigned int width
, height
, y
;
988 if (region
->Left
> region
->Right
|| region
->Top
> region
->Bottom
)
990 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
993 if (size
.X
<= coord
.X
|| size
.Y
<= coord
.Y
)
995 region
->Right
= region
->Left
- 1;
996 region
->Bottom
= region
->Top
- 1;
997 SetLastError( ERROR_INVALID_FUNCTION
);
1000 width
= min( region
->Right
- region
->Left
+ 1, size
.X
- coord
.X
);
1001 height
= min( region
->Bottom
- region
->Top
+ 1, size
.Y
- coord
.Y
);
1002 region
->Right
= region
->Left
+ width
- 1;
1003 region
->Bottom
= region
->Top
+ height
- 1;
1005 count
= sizeof(*result
) + width
* height
* sizeof(*buffer
);
1006 if (!(result
= HeapAlloc( GetProcessHeap(), 0, count
)))
1008 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1012 params
.mode
= CHAR_INFO_MODE_TEXTATTR
;
1013 params
.x
= region
->Left
;
1014 params
.y
= region
->Top
;
1015 params
.width
= width
;
1016 if ((ret
= console_ioctl( handle
, IOCTL_CONDRV_READ_OUTPUT
, ¶ms
, sizeof(params
), result
, count
, &count
)) && count
)
1018 CHAR_INFO
*char_info
= (CHAR_INFO
*)(result
+ 1);
1020 width
= region
->Right
- region
->Left
+ 1;
1021 height
= region
->Bottom
- region
->Top
+ 1;
1022 for (y
= 0; y
< height
; y
++)
1023 memcpy( &buffer
[(y
+ coord
.Y
) * size
.X
+ coord
.X
], &char_info
[y
* width
], width
* sizeof(*buffer
) );
1025 HeapFree( GetProcessHeap(), 0, result
);
1030 /******************************************************************************
1031 * ScrollConsoleScreenBufferA (kernelbase.@)
1033 BOOL WINAPI DECLSPEC_HOTPATCH
ScrollConsoleScreenBufferA( HANDLE handle
, const SMALL_RECT
*scroll
,
1034 const SMALL_RECT
*clip
, COORD origin
, const CHAR_INFO
*fill
)
1038 ciW
.Attributes
= fill
->Attributes
;
1039 MultiByteToWideChar( GetConsoleOutputCP(), 0, &fill
->Char
.AsciiChar
, 1, &ciW
.Char
.UnicodeChar
, 1 );
1041 return ScrollConsoleScreenBufferW( handle
, scroll
, clip
, origin
, &ciW
);
1045 /******************************************************************************
1046 * ScrollConsoleScreenBufferW (kernelbase.@)
1048 BOOL WINAPI DECLSPEC_HOTPATCH
ScrollConsoleScreenBufferW( HANDLE handle
, const SMALL_RECT
*scroll
,
1049 const SMALL_RECT
*clip_rect
, COORD origin
,
1050 const CHAR_INFO
*fill
)
1052 struct condrv_scroll_params params
;
1055 TRACE( "(%p,(%d,%d-%d,%d),(%d,%d-%d,%d),%d-%d,%p)\n", handle
,
1056 scroll
->Left
, scroll
->Top
, scroll
->Right
, scroll
->Bottom
,
1057 clip_rect
->Left
, clip_rect
->Top
, clip_rect
->Right
, clip_rect
->Bottom
,
1058 origin
.X
, origin
.Y
, fill
);
1060 TRACE("(%p,(%d,%d-%d,%d),(nil),%d-%d,%p)\n", handle
,
1061 scroll
->Left
, scroll
->Top
, scroll
->Right
, scroll
->Bottom
,
1062 origin
.X
, origin
.Y
, fill
);
1064 params
.scroll
= *scroll
;
1065 params
.origin
= origin
;
1066 params
.fill
.ch
= fill
->Char
.UnicodeChar
;
1067 params
.fill
.attr
= fill
->Attributes
;
1070 params
.clip
.Left
= params
.clip
.Top
= 0;
1071 params
.clip
.Right
= params
.clip
.Bottom
= SHRT_MAX
;
1073 else params
.clip
= *clip_rect
;
1074 return console_ioctl( handle
, IOCTL_CONDRV_SCROLL
, (void *)¶ms
, sizeof(params
), NULL
, 0, NULL
);
1078 /******************************************************************************
1079 * SetConsoleActiveScreenBuffer (kernelbase.@)
1081 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleActiveScreenBuffer( HANDLE handle
)
1083 TRACE( "(%p)\n", handle
);
1084 return console_ioctl( handle
, IOCTL_CONDRV_ACTIVATE
, NULL
, 0, NULL
, 0, NULL
);
1088 /******************************************************************************
1089 * SetConsoleCP (kernelbase.@)
1091 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleCP( UINT cp
)
1093 struct condrv_input_info_params params
= { SET_CONSOLE_INPUT_INFO_INPUT_CODEPAGE
};
1095 params
.info
.input_cp
= cp
;
1096 return console_ioctl( RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
,
1097 IOCTL_CONDRV_SET_INPUT_INFO
, ¶ms
, sizeof(params
), NULL
, 0, NULL
);
1101 /******************************************************************************
1102 * SetConsoleCtrlHandler (kernelbase.@)
1104 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleCtrlHandler( PHANDLER_ROUTINE func
, BOOL add
)
1106 struct ctrl_handler
*handler
;
1109 TRACE( "(%p,%d)\n", func
, add
);
1111 RtlEnterCriticalSection( &console_section
);
1115 if (add
) NtCurrentTeb()->Peb
->ProcessParameters
->ConsoleFlags
|= 1;
1116 else NtCurrentTeb()->Peb
->ProcessParameters
->ConsoleFlags
&= ~1;
1121 if ((handler
= RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*handler
) )))
1123 handler
->func
= func
;
1124 handler
->next
= ctrl_handlers
;
1125 ctrl_handlers
= handler
;
1131 struct ctrl_handler
**p_handler
;
1133 for (p_handler
= &ctrl_handlers
; *p_handler
; p_handler
= &(*p_handler
)->next
)
1135 if ((*p_handler
)->func
== func
) break;
1137 if (*p_handler
&& *p_handler
!= &default_handler
)
1139 handler
= *p_handler
;
1140 *p_handler
= handler
->next
;
1141 RtlFreeHeap( GetProcessHeap(), 0, handler
);
1144 else SetLastError( ERROR_INVALID_PARAMETER
);
1147 RtlLeaveCriticalSection( &console_section
);
1152 /******************************************************************************
1153 * SetConsoleCursorInfo (kernelbase.@)
1155 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleCursorInfo( HANDLE handle
, CONSOLE_CURSOR_INFO
*info
)
1157 struct condrv_output_info_params params
= { SET_CONSOLE_OUTPUT_INFO_CURSOR_GEOM
};
1159 TRACE( "(%p,%d,%d)\n", handle
, info
->dwSize
, info
->bVisible
);
1161 params
.info
.cursor_size
= info
->dwSize
;
1162 params
.info
.cursor_visible
= info
->bVisible
;
1163 return console_ioctl( handle
, IOCTL_CONDRV_SET_OUTPUT_INFO
, ¶ms
, sizeof(params
),
1168 /******************************************************************************
1169 * SetConsoleCursorPosition (kernelbase.@)
1171 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleCursorPosition( HANDLE handle
, COORD pos
)
1173 struct condrv_output_info_params params
= { SET_CONSOLE_OUTPUT_INFO_CURSOR_POS
};
1175 TRACE( "%p %d %d\n", handle
, pos
.X
, pos
.Y
);
1177 params
.info
.cursor_x
= pos
.X
;
1178 params
.info
.cursor_y
= pos
.Y
;
1179 return console_ioctl( handle
, IOCTL_CONDRV_SET_OUTPUT_INFO
, ¶ms
, sizeof(params
), NULL
, 0, NULL
);
1183 /******************************************************************************
1184 * SetConsoleInputExeNameA (kernelbase.@)
1186 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleInputExeNameA( LPCSTR name
)
1188 if (!name
|| !name
[0])
1190 SetLastError( ERROR_INVALID_PARAMETER
);
1193 RtlEnterCriticalSection( &console_section
);
1194 MultiByteToWideChar( CP_ACP
, 0, name
, -1, input_exe
, ARRAY_SIZE(input_exe
) );
1195 RtlLeaveCriticalSection( &console_section
);
1200 /******************************************************************************
1201 * SetConsoleInputExeNameW (kernelbase.@)
1203 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleInputExeNameW( LPCWSTR name
)
1205 if (!name
|| !name
[0])
1207 SetLastError( ERROR_INVALID_PARAMETER
);
1210 RtlEnterCriticalSection( &console_section
);
1211 lstrcpynW( input_exe
, name
, ARRAY_SIZE(input_exe
) );
1212 RtlLeaveCriticalSection( &console_section
);
1217 /******************************************************************************
1218 * SetConsoleMode (kernelbase.@)
1220 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleMode( HANDLE handle
, DWORD mode
)
1222 TRACE( "(%p,%x)\n", handle
, mode
);
1223 return console_ioctl( handle
, IOCTL_CONDRV_SET_MODE
, &mode
, sizeof(mode
), NULL
, 0, NULL
);
1227 /******************************************************************************
1228 * SetConsoleOutputCP (kernelbase.@)
1230 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleOutputCP( UINT cp
)
1232 struct condrv_input_info_params params
= { SET_CONSOLE_INPUT_INFO_OUTPUT_CODEPAGE
};
1234 params
.info
.output_cp
= cp
;
1235 return console_ioctl( RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
,
1236 IOCTL_CONDRV_SET_INPUT_INFO
, ¶ms
, sizeof(params
), NULL
, 0, NULL
);
1240 /******************************************************************************
1241 * SetConsoleScreenBufferInfoEx (kernelbase.@)
1243 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleScreenBufferInfoEx( HANDLE handle
,
1244 CONSOLE_SCREEN_BUFFER_INFOEX
*info
)
1246 struct condrv_output_info_params params
=
1247 { SET_CONSOLE_OUTPUT_INFO_CURSOR_POS
| SET_CONSOLE_OUTPUT_INFO_SIZE
|
1248 SET_CONSOLE_OUTPUT_INFO_ATTR
| SET_CONSOLE_OUTPUT_INFO_POPUP_ATTR
|
1249 SET_CONSOLE_OUTPUT_INFO_DISPLAY_WINDOW
| SET_CONSOLE_OUTPUT_INFO_MAX_SIZE
};
1251 TRACE("(%p, %p)\n", handle
, info
);
1253 if (info
->cbSize
!= sizeof(CONSOLE_SCREEN_BUFFER_INFOEX
))
1255 SetLastError(ERROR_INVALID_PARAMETER
);
1259 params
.info
.width
= info
->dwSize
.X
;
1260 params
.info
.height
= info
->dwSize
.Y
;
1261 params
.info
.cursor_x
= info
->dwCursorPosition
.X
;
1262 params
.info
.cursor_y
= info
->dwCursorPosition
.Y
;
1263 params
.info
.attr
= info
->wAttributes
;
1264 params
.info
.win_left
= info
->srWindow
.Left
;
1265 params
.info
.win_top
= info
->srWindow
.Top
;
1266 params
.info
.win_right
= info
->srWindow
.Right
;
1267 params
.info
.win_bottom
= info
->srWindow
.Bottom
;
1268 params
.info
.popup_attr
= info
->wPopupAttributes
;
1269 params
.info
.max_width
= min( info
->dwMaximumWindowSize
.X
, info
->dwSize
.X
);
1270 params
.info
.max_height
= min( info
->dwMaximumWindowSize
.Y
, info
->dwSize
.Y
);
1271 return console_ioctl( handle
, IOCTL_CONDRV_SET_OUTPUT_INFO
, ¶ms
, sizeof(params
), NULL
, 0, NULL
);
1275 /******************************************************************************
1276 * SetConsoleScreenBufferSize (kernelbase.@)
1278 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleScreenBufferSize( HANDLE handle
, COORD size
)
1280 struct condrv_output_info_params params
= { SET_CONSOLE_OUTPUT_INFO_SIZE
};
1282 TRACE( "(%p,(%d,%d))\n", handle
, size
.X
, size
.Y
);
1284 params
.info
.width
= size
.X
;
1285 params
.info
.height
= size
.Y
;
1286 return console_ioctl( handle
, IOCTL_CONDRV_SET_OUTPUT_INFO
, ¶ms
, sizeof(params
), NULL
, 0, NULL
);
1290 /******************************************************************************
1291 * SetConsoleTextAttribute (kernelbase.@)
1293 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleTextAttribute( HANDLE handle
, WORD attr
)
1295 struct condrv_output_info_params params
= { SET_CONSOLE_OUTPUT_INFO_ATTR
};
1297 TRACE( "(%p,%d)\n", handle
, attr
);
1299 params
.info
.attr
= attr
;
1300 return console_ioctl( handle
, IOCTL_CONDRV_SET_OUTPUT_INFO
, ¶ms
, sizeof(params
), NULL
, 0, NULL
);
1304 /******************************************************************************
1305 * SetConsoleTitleW (kernelbase.@)
1307 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleTitleW( LPCWSTR title
)
1309 TRACE( "%s\n", debugstr_w( title
));
1311 return console_ioctl( RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
, IOCTL_CONDRV_SET_TITLE
,
1312 (void *)title
, lstrlenW(title
) * sizeof(WCHAR
), NULL
, 0, NULL
);
1316 /******************************************************************************
1317 * SetConsoleWindowInfo (kernelbase.@)
1319 BOOL WINAPI DECLSPEC_HOTPATCH
SetConsoleWindowInfo( HANDLE handle
, BOOL absolute
, SMALL_RECT
*window
)
1321 struct condrv_output_info_params params
= { SET_CONSOLE_OUTPUT_INFO_DISPLAY_WINDOW
};
1322 SMALL_RECT rect
= *window
;
1324 TRACE( "(%p,%d,(%d,%d-%d,%d))\n", handle
, absolute
, rect
.Left
, rect
.Top
, rect
.Right
, rect
.Bottom
);
1328 CONSOLE_SCREEN_BUFFER_INFO info
;
1330 if (!GetConsoleScreenBufferInfo( handle
, &info
)) return FALSE
;
1331 rect
.Left
+= info
.srWindow
.Left
;
1332 rect
.Top
+= info
.srWindow
.Top
;
1333 rect
.Right
+= info
.srWindow
.Right
;
1334 rect
.Bottom
+= info
.srWindow
.Bottom
;
1337 params
.info
.win_left
= rect
.Left
;
1338 params
.info
.win_top
= rect
.Top
;
1339 params
.info
.win_right
= rect
.Right
;
1340 params
.info
.win_bottom
= rect
.Bottom
;
1341 return console_ioctl( handle
, IOCTL_CONDRV_SET_OUTPUT_INFO
, ¶ms
, sizeof(params
), NULL
, 0, NULL
);
1345 /***********************************************************************
1346 * ReadConsoleInputA (kernelbase.@)
1348 BOOL WINAPI
ReadConsoleInputA( HANDLE handle
, INPUT_RECORD
*buffer
, DWORD length
, DWORD
*count
)
1352 if (!ReadConsoleInputW( handle
, buffer
, length
, &read
)) return FALSE
;
1353 input_records_WtoA( buffer
, read
);
1354 if (count
) *count
= read
;
1359 /***********************************************************************
1360 * ReadConsoleInputW (kernelbase.@)
1362 BOOL WINAPI
ReadConsoleInputW( HANDLE handle
, INPUT_RECORD
*buffer
, DWORD length
, DWORD
*count
)
1364 if (!console_ioctl( handle
, IOCTL_CONDRV_READ_INPUT
, NULL
, 0,
1365 buffer
, length
* sizeof(*buffer
), count
))
1367 *count
/= sizeof(*buffer
);
1372 /******************************************************************************
1373 * WriteConsoleInputA (kernelbase.@)
1375 BOOL WINAPI DECLSPEC_HOTPATCH
WriteConsoleInputA( HANDLE handle
, const INPUT_RECORD
*buffer
,
1376 DWORD count
, DWORD
*written
)
1378 INPUT_RECORD
*recW
= NULL
;
1385 SetLastError( ERROR_INVALID_ACCESS
);
1388 if (!(recW
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(*recW
) )))
1390 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1393 memcpy( recW
, buffer
, count
* sizeof(*recW
) );
1394 input_records_AtoW( recW
, count
);
1396 ret
= WriteConsoleInputW( handle
, recW
, count
, written
);
1397 HeapFree( GetProcessHeap(), 0, recW
);
1402 /******************************************************************************
1403 * WriteConsoleInputW (kernelbase.@)
1405 BOOL WINAPI DECLSPEC_HOTPATCH
WriteConsoleInputW( HANDLE handle
, const INPUT_RECORD
*buffer
,
1406 DWORD count
, DWORD
*written
)
1408 TRACE( "(%p,%p,%d,%p)\n", handle
, buffer
, count
, written
);
1410 if (count
> 0 && !buffer
)
1412 SetLastError( ERROR_INVALID_ACCESS
);
1416 if (!DeviceIoControl( handle
, IOCTL_CONDRV_WRITE_INPUT
, (void *)buffer
, count
* sizeof(*buffer
), NULL
, 0, NULL
, NULL
))
1421 SetLastError( ERROR_INVALID_ACCESS
);
1429 /***********************************************************************
1430 * WriteConsoleOutputA (kernelbase.@)
1432 BOOL WINAPI DECLSPEC_HOTPATCH
WriteConsoleOutputA( HANDLE handle
, const CHAR_INFO
*buffer
,
1433 COORD size
, COORD coord
, SMALL_RECT
*region
)
1437 COORD new_size
, new_coord
;
1440 new_size
.X
= min( region
->Right
- region
->Left
+ 1, size
.X
- coord
.X
);
1441 new_size
.Y
= min( region
->Bottom
- region
->Top
+ 1, size
.Y
- coord
.Y
);
1443 if (new_size
.X
<= 0 || new_size
.Y
<= 0)
1445 region
->Bottom
= region
->Top
+ new_size
.Y
- 1;
1446 region
->Right
= region
->Left
+ new_size
.X
- 1;
1450 /* only copy the useful rectangle */
1451 if (!(ciW
= HeapAlloc( GetProcessHeap(), 0, sizeof(CHAR_INFO
) * new_size
.X
* new_size
.Y
)))
1453 for (y
= 0; y
< new_size
.Y
; y
++)
1454 memcpy( &ciW
[y
* new_size
.X
], &buffer
[(y
+ coord
.Y
) * size
.X
+ coord
.X
],
1455 new_size
.X
* sizeof(CHAR_INFO
) );
1456 char_info_AtoW( ciW
, new_size
.X
* new_size
.Y
);
1457 new_coord
.X
= new_coord
.Y
= 0;
1458 ret
= WriteConsoleOutputW( handle
, ciW
, new_size
, new_coord
, region
);
1459 HeapFree( GetProcessHeap(), 0, ciW
);
1464 /***********************************************************************
1465 * WriteConsoleOutputW (kernelbase.@)
1467 BOOL WINAPI DECLSPEC_HOTPATCH
WriteConsoleOutputW( HANDLE handle
, const CHAR_INFO
*buffer
,
1468 COORD size
, COORD coord
, SMALL_RECT
*region
)
1470 struct condrv_output_params
*params
;
1471 unsigned int width
, height
, y
;
1475 TRACE( "(%p,%p,(%d,%d),(%d,%d),(%d,%dx%d,%d)\n",
1476 handle
, buffer
, size
.X
, size
.Y
, coord
.X
, coord
.Y
,
1477 region
->Left
, region
->Top
, region
->Right
, region
->Bottom
);
1479 if (region
->Left
> region
->Right
|| region
->Top
> region
->Bottom
|| size
.X
<= coord
.X
|| size
.Y
<= coord
.Y
)
1481 SetLastError( ERROR_INVALID_PARAMETER
);
1485 width
= min( region
->Right
- region
->Left
+ 1, size
.X
- coord
.X
);
1486 height
= min( region
->Bottom
- region
->Top
+ 1, size
.Y
- coord
.Y
);
1487 region
->Right
= region
->Left
+ width
- 1;
1488 region
->Bottom
= region
->Top
+ height
- 1;
1490 params_size
= sizeof(*params
) + width
* height
* sizeof(*buffer
);
1491 if (!(params
= HeapAlloc( GetProcessHeap(), 0, params_size
)))
1493 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1497 params
->mode
= CHAR_INFO_MODE_TEXTATTR
;
1498 params
->x
= region
->Left
;
1499 params
->y
= region
->Top
;
1500 params
->width
= width
;
1502 for (y
= 0; y
< height
; y
++)
1503 memcpy( &((CHAR_INFO
*)(params
+ 1))[y
* width
], &buffer
[(y
+ coord
.Y
) * size
.X
+ coord
.X
], width
* sizeof(CHAR_INFO
) );
1505 ret
= console_ioctl( handle
, IOCTL_CONDRV_WRITE_OUTPUT
, params
, params_size
, region
, sizeof(*region
), NULL
);
1506 HeapFree( GetProcessHeap(), 0, params
);
1511 /******************************************************************************
1512 * WriteConsoleOutputAttribute (kernelbase.@)
1514 BOOL WINAPI DECLSPEC_HOTPATCH
WriteConsoleOutputAttribute( HANDLE handle
, const WORD
*attr
, DWORD length
,
1515 COORD coord
, DWORD
*written
)
1517 struct condrv_output_params
*params
;
1521 TRACE( "(%p,%p,%d,%dx%d,%p)\n", handle
, attr
, length
, coord
.X
, coord
.Y
, written
);
1523 if ((length
> 0 && !attr
) || !written
)
1525 SetLastError( ERROR_INVALID_ACCESS
);
1530 size
= sizeof(*params
) + length
* sizeof(WORD
);
1531 if (!(params
= HeapAlloc( GetProcessHeap(), 0, size
))) return FALSE
;
1532 params
->mode
= CHAR_INFO_MODE_ATTR
;
1533 params
->x
= coord
.X
;
1534 params
->y
= coord
.Y
;
1536 memcpy( params
+ 1, attr
, length
* sizeof(*attr
) );
1537 ret
= console_ioctl( handle
, IOCTL_CONDRV_WRITE_OUTPUT
, params
, size
, written
, sizeof(*written
), NULL
);
1538 HeapFree( GetProcessHeap(), 0, params
);
1543 /******************************************************************************
1544 * WriteConsoleOutputCharacterA (kernelbase.@)
1546 BOOL WINAPI DECLSPEC_HOTPATCH
WriteConsoleOutputCharacterA( HANDLE handle
, LPCSTR str
, DWORD length
,
1547 COORD coord
, DWORD
*written
)
1553 TRACE( "(%p,%s,%d,%dx%d,%p)\n", handle
, debugstr_an(str
, length
), length
, coord
.X
, coord
.Y
, written
);
1557 UINT cp
= GetConsoleOutputCP();
1560 SetLastError( ERROR_INVALID_ACCESS
);
1563 lenW
= MultiByteToWideChar( cp
, 0, str
, length
, NULL
, 0 );
1565 if (!(strW
= HeapAlloc( GetProcessHeap(), 0, lenW
* sizeof(WCHAR
) )))
1567 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1570 MultiByteToWideChar( cp
, 0, str
, length
, strW
, lenW
);
1572 ret
= WriteConsoleOutputCharacterW( handle
, strW
, lenW
, coord
, written
);
1573 HeapFree( GetProcessHeap(), 0, strW
);
1578 /******************************************************************************
1579 * WriteConsoleOutputCharacterW (kernelbase.@)
1581 BOOL WINAPI DECLSPEC_HOTPATCH
WriteConsoleOutputCharacterW( HANDLE handle
, LPCWSTR str
, DWORD length
,
1582 COORD coord
, DWORD
*written
)
1584 struct condrv_output_params
*params
;
1588 TRACE( "(%p,%s,%d,%dx%d,%p)\n", handle
, debugstr_wn(str
, length
), length
, coord
.X
, coord
.Y
, written
);
1590 if ((length
> 0 && !str
) || !written
)
1592 SetLastError( ERROR_INVALID_ACCESS
);
1597 size
= sizeof(*params
) + length
* sizeof(WCHAR
);
1598 if (!(params
= HeapAlloc( GetProcessHeap(), 0, size
))) return FALSE
;
1599 params
->mode
= CHAR_INFO_MODE_TEXT
;
1600 params
->x
= coord
.X
;
1601 params
->y
= coord
.Y
;
1603 memcpy( params
+ 1, str
, length
* sizeof(*str
) );
1604 ret
= console_ioctl( handle
, IOCTL_CONDRV_WRITE_OUTPUT
, params
, size
, written
, sizeof(*written
), NULL
);
1605 HeapFree( GetProcessHeap(), 0, params
);
1610 /***********************************************************************
1611 * ReadConsoleA (kernelbase.@)
1613 BOOL WINAPI
ReadConsoleA( HANDLE handle
, void *buffer
, DWORD length
, DWORD
*ret_count
, void *reserved
)
1615 LPWSTR strW
= HeapAlloc( GetProcessHeap(), 0, length
* sizeof(WCHAR
) );
1621 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1624 if ((ret
= ReadConsoleW( handle
, strW
, length
, &count
, NULL
)))
1626 count
= WideCharToMultiByte( GetConsoleCP(), 0, strW
, count
, buffer
, length
, NULL
, NULL
);
1627 if (ret_count
) *ret_count
= count
;
1629 HeapFree( GetProcessHeap(), 0, strW
);
1634 /***********************************************************************
1635 * ReadConsoleW (kernelbase.@)
1637 BOOL WINAPI
ReadConsoleW( HANDLE handle
, void *buffer
, DWORD length
, DWORD
*count
, void *reserved
)
1641 TRACE( "(%p,%p,%d,%p,%p)\n", handle
, buffer
, length
, count
, reserved
);
1643 if (length
> INT_MAX
)
1645 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1649 ret
= console_ioctl( handle
, IOCTL_CONDRV_READ_CONSOLE
, NULL
, 0, buffer
,
1650 length
* sizeof(WCHAR
), count
);
1651 if (ret
) *count
/= sizeof(WCHAR
);
1656 /***********************************************************************
1657 * WriteConsoleA (kernelbase.@)
1659 BOOL WINAPI DECLSPEC_HOTPATCH
WriteConsoleA( HANDLE handle
, const void *buffer
, DWORD length
,
1660 DWORD
*written
, void *reserved
)
1662 UINT cp
= GetConsoleOutputCP();
1667 if (written
) *written
= 0;
1668 lenW
= MultiByteToWideChar( cp
, 0, buffer
, length
, NULL
, 0 );
1669 if (!(strW
= HeapAlloc( GetProcessHeap(), 0, lenW
* sizeof(WCHAR
) ))) return FALSE
;
1670 MultiByteToWideChar( cp
, 0, buffer
, length
, strW
, lenW
);
1671 ret
= WriteConsoleW( handle
, strW
, lenW
, written
, 0 );
1672 HeapFree( GetProcessHeap(), 0, strW
);
1677 /***********************************************************************
1678 * WriteConsoleW (kernelbase.@)
1680 BOOL WINAPI DECLSPEC_HOTPATCH
WriteConsoleW( HANDLE handle
, const void *buffer
, DWORD length
,
1681 DWORD
*written
, void *reserved
)
1685 TRACE( "(%p,%s,%d,%p,%p)\n", handle
, debugstr_wn(buffer
, length
), length
, written
, reserved
);
1687 ret
= console_ioctl( handle
, IOCTL_CONDRV_WRITE_CONSOLE
, (void *)buffer
,
1688 length
* sizeof(WCHAR
), NULL
, 0, NULL
);
1689 if (written
) *written
= ret
? length
: 0;
1694 /***********************************************************************
1695 * FlushConsoleInputBuffer (kernelbase.@)
1697 BOOL WINAPI
FlushConsoleInputBuffer( HANDLE handle
)
1699 return console_ioctl( handle
, IOCTL_CONDRV_FLUSH
, NULL
, 0, NULL
, 0, NULL
);
1703 /***********************************************************************
1704 * Beep (kernelbase.@)
1706 BOOL WINAPI
Beep( DWORD frequency
, DWORD duration
)
1708 /* FIXME: we should not require a console to be attached */
1709 console_ioctl( RtlGetCurrentPeb()->ProcessParameters
->ConsoleHandle
,
1710 IOCTL_CONDRV_BEEP
, NULL
, 0, NULL
, 0, NULL
);
1715 static HANDLE
create_pseudo_console( COORD size
, HANDLE input
, HANDLE output
, HANDLE signal
,
1716 DWORD flags
, HANDLE
*process
)
1718 WCHAR cmd
[MAX_PATH
], conhost_path
[MAX_PATH
];
1719 PROCESS_INFORMATION pi
;
1720 HANDLE server
, console
;
1725 if (!(server
= create_console_server())) return NULL
;
1727 console
= create_console_reference( server
);
1734 memset( &si
, 0, sizeof(si
) );
1735 si
.StartupInfo
.cb
= sizeof(STARTUPINFOEXW
);
1736 si
.StartupInfo
.hStdInput
= input
;
1737 si
.StartupInfo
.hStdOutput
= output
;
1738 si
.StartupInfo
.hStdError
= output
;
1739 si
.StartupInfo
.dwFlags
= STARTF_USESTDHANDLES
;
1740 swprintf( conhost_path
, ARRAY_SIZE(conhost_path
), L
"%s\\conhost.exe", system_dir
);
1743 swprintf( cmd
, ARRAY_SIZE(cmd
),
1744 L
"\"%s\" --headless %s--width %u --height %u --signal 0x%x --server 0x%x",
1745 conhost_path
, (flags
& PSEUDOCONSOLE_INHERIT_CURSOR
) ? L
"--inheritcursor " : L
"",
1746 size
.X
, size
.Y
, signal
, server
);
1750 swprintf( cmd
, ARRAY_SIZE(cmd
), L
"\"%s\" --unix --width %u --height %u --server 0x%x",
1751 conhost_path
, size
.X
, size
.Y
, server
);
1753 Wow64DisableWow64FsRedirection( &redir
);
1754 res
= CreateProcessW( conhost_path
, cmd
, NULL
, NULL
, TRUE
, DETACHED_PROCESS
, NULL
, NULL
,
1755 &si
.StartupInfo
, &pi
);
1756 Wow64RevertWow64FsRedirection( redir
);
1764 NtClose( pi
.hThread
);
1765 *process
= pi
.hProcess
;
1769 /******************************************************************************
1770 * CreatePseudoConsole (kernelbase.@)
1772 HRESULT WINAPI
CreatePseudoConsole( COORD size
, HANDLE input
, HANDLE output
, DWORD flags
, HPCON
*ret
)
1774 SECURITY_ATTRIBUTES inherit_attr
= { sizeof(inherit_attr
), NULL
, TRUE
};
1775 struct pseudo_console
*pseudo_console
;
1776 HANDLE tty_input
= NULL
, tty_output
;
1777 HANDLE signal
= NULL
;
1778 WCHAR pipe_name
[64];
1780 TRACE( "(%u,%u) %p %p %x %p\n", size
.X
, size
.Y
, input
, output
, flags
, ret
);
1782 if (!size
.X
|| !size
.Y
|| !ret
) return E_INVALIDARG
;
1784 if (!(pseudo_console
= HeapAlloc( GetProcessHeap(), 0, HEAP_ZERO_MEMORY
))) return E_OUTOFMEMORY
;
1786 swprintf( pipe_name
, ARRAY_SIZE(pipe_name
), L
"\\\\.\\pipe\\wine_pty_signal_pipe%x",
1787 GetCurrentThreadId() );
1788 signal
= CreateNamedPipeW( pipe_name
, PIPE_ACCESS_INBOUND
| FILE_FLAG_OVERLAPPED
, PIPE_TYPE_BYTE
,
1789 PIPE_UNLIMITED_INSTANCES
, 4096, 4096, NMPWAIT_USE_DEFAULT_WAIT
, &inherit_attr
);
1790 if (signal
== INVALID_HANDLE_VALUE
)
1792 HeapFree( GetProcessHeap(), 0, pseudo_console
);
1793 return HRESULT_FROM_WIN32( GetLastError() );
1795 pseudo_console
->signal
= CreateFileW( pipe_name
, GENERIC_WRITE
, 0, NULL
, OPEN_EXISTING
, 0, NULL
);
1796 if (pseudo_console
->signal
!= INVALID_HANDLE_VALUE
&&
1797 DuplicateHandle( GetCurrentProcess(), input
, GetCurrentProcess(), &tty_input
, 0, TRUE
, DUPLICATE_SAME_ACCESS
) &&
1798 DuplicateHandle( GetCurrentProcess(), output
, GetCurrentProcess(), &tty_output
, 0, TRUE
, DUPLICATE_SAME_ACCESS
))
1800 pseudo_console
->reference
= create_pseudo_console( size
, tty_input
, tty_output
, signal
, flags
,
1801 &pseudo_console
->process
);
1802 NtClose( tty_output
);
1804 NtClose( tty_input
);
1806 if (!pseudo_console
->reference
)
1808 ClosePseudoConsole( pseudo_console
);
1809 return HRESULT_FROM_WIN32( GetLastError() );
1812 *ret
= pseudo_console
;
1816 /******************************************************************************
1817 * ClosePseudoConsole (kernelbase.@)
1819 void WINAPI
ClosePseudoConsole( HPCON handle
)
1821 struct pseudo_console
*pseudo_console
= handle
;
1823 TRACE( "%p\n", handle
);
1825 if (!pseudo_console
) return;
1826 if (pseudo_console
->signal
) CloseHandle( pseudo_console
->signal
);
1827 if (pseudo_console
->process
)
1829 WaitForSingleObject( pseudo_console
->process
, INFINITE
);
1830 CloseHandle( pseudo_console
->process
);
1832 if (pseudo_console
->reference
) CloseHandle( pseudo_console
->reference
);
1835 /******************************************************************************
1836 * ResizePseudoConsole (kernelbase.@)
1838 HRESULT WINAPI
ResizePseudoConsole( HPCON handle
, COORD size
)
1840 FIXME( "%p (%u,%u)\n", handle
, size
.X
, size
.Y
);
1844 static BOOL
is_tty_handle( HANDLE handle
)
1846 return ((UINT_PTR
)handle
& 3) == 1;
1849 void init_console( void )
1851 RTL_USER_PROCESS_PARAMETERS
*params
= RtlGetCurrentPeb()->ProcessParameters
;
1853 if (params
->ConsoleHandle
== CONSOLE_HANDLE_SHELL
)
1855 HANDLE tty_in
= NULL
, tty_out
= NULL
, process
= NULL
;
1858 if (is_tty_handle( params
->hStdInput
))
1860 tty_in
= params
->hStdInput
;
1861 params
->hStdInput
= NULL
;
1863 if (is_tty_handle( params
->hStdOutput
))
1865 tty_out
= params
->hStdOutput
;
1866 params
->hStdOutput
= NULL
;
1868 if (is_tty_handle( params
->hStdError
))
1870 if (tty_out
) CloseHandle( params
->hStdError
);
1871 else tty_out
= params
->hStdError
;
1872 params
->hStdError
= NULL
;
1875 size
.X
= params
->dwXCountChars
;
1876 size
.Y
= params
->dwYCountChars
;
1877 TRACE( "creating unix console (size %u %u)\n", size
.X
, size
.Y
);
1878 params
->ConsoleHandle
= create_pseudo_console( size
, tty_in
, tty_out
, NULL
, 0, &process
);
1879 CloseHandle( process
);
1880 CloseHandle( tty_in
);
1881 CloseHandle( tty_out
);
1883 if (params
->ConsoleHandle
&& create_console_connection( params
->ConsoleHandle
))
1885 init_console_std_handles( FALSE
);
1889 else if (params
->ConsoleHandle
== CONSOLE_HANDLE_ALLOC
)
1891 HMODULE mod
= GetModuleHandleW( NULL
);
1892 params
->ConsoleHandle
= NULL
;
1893 if (RtlImageNtHeader( mod
)->OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_WINDOWS_CUI
)
1896 else if (params
->ConsoleHandle
) create_console_connection( params
->ConsoleHandle
);
1898 RtlAddVectoredExceptionHandler( FALSE
, handle_ctrl_c
);