kernelbase: Use IOCTL_CONDRV_READ_OUTPUT in ReadConsoleOutputAttribute.
[wine.git] / dlls / kernelbase / console.c
bloba4b9b8c49126f1756ca5ce61ca941b7744f22f6f
1 /*
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
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <limits.h>
31 #define NONAMELESSUNION
32 #include "ntstatus.h"
33 #define WIN32_NO_STATUS
34 #include "windef.h"
35 #include "winbase.h"
36 #include "winnls.h"
37 #include "winerror.h"
38 #include "wincon.h"
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];
61 struct ctrl_handler
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 );
71 return TRUE;
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 )
86 IO_STATUS_BLOCK io;
87 NTSTATUS status;
89 status = NtDeviceIoControlFile( handle, NULL, NULL, NULL, &io, code, in_buff, in_count,
90 out_buff, out_count );
91 switch( status )
93 case STATUS_SUCCESS:
94 if (read) *read = io.Information;
95 return TRUE;
96 case STATUS_INVALID_PARAMETER:
97 break;
98 default:
99 status = STATUS_INVALID_HANDLE;
100 break;
102 if (read) *read = 0;
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();
110 int i;
111 char ch;
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();
125 int i;
126 WCHAR ch;
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 )
139 char ch;
141 while (count-- > 0)
143 WideCharToMultiByte( cp, 0, &buffer->Char.UnicodeChar, 1, &ch, 1, NULL, NULL );
144 buffer->Char.AsciiChar = ch;
145 buffer++;
149 /* map char infos to Unicode */
150 static void char_info_AtoW( CHAR_INFO *buffer, int count )
152 UINT cp = GetConsoleOutputCP();
153 WCHAR ch;
155 while (count-- > 0)
157 MultiByteToWideChar( cp, 0, &buffer->Char.AsciiChar, 1, &ch, 1 );
158 buffer->Char.UnicodeChar = ch;
159 buffer++;
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;
169 params.x = i;
170 params.y = j;
171 params.count = len;
172 params.wrap = FALSE;
173 params.ch = fill->Char.UnicodeChar;
174 params.attr = fill->Attributes;
175 console_ioctl( handle, IOCTL_CONDRV_FILL_OUTPUT, &params, 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;
182 COORD c = { 0, 0 };
184 if (!console_ioctl( handle, IOCTL_CONDRV_GET_OUTPUT_INFO, NULL, 0, &info, sizeof(info), NULL ))
185 return c;
187 c.X = info.max_width;
188 c.Y = info.max_height;
189 TRACE( "(%p), returning %dx%d\n", handle, c.X, c.Y );
190 return c;
193 /******************************************************************
194 * AttachConsole (kernelbase.@)
196 BOOL WINAPI DECLSPEC_HOTPATCH AttachConsole( DWORD pid )
198 BOOL ret;
200 TRACE( "(%x)\n", pid );
202 SERVER_START_REQ( attach_console )
204 req->pid = pid;
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 ));
212 SERVER_END_REQ;
213 return ret;
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;
229 HANDLE event;
230 DWORD mode;
231 BOOL ret;
233 TRACE("()\n");
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 );
240 return FALSE;
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;
264 if (app_si.lpTitle)
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) )
298 goto error;
300 else
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 );
311 return TRUE;
313 error:
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);
318 FreeConsole();
319 return FALSE;
323 /******************************************************************************
324 * CreateConsoleScreenBuffer (kernelbase.@)
326 HANDLE WINAPI DECLSPEC_HOTPATCH CreateConsoleScreenBuffer( DWORD access, DWORD share,
327 SECURITY_ATTRIBUTES *sa, DWORD flags,
328 void *data )
330 OBJECT_ATTRIBUTES attr = {sizeof(attr)};
331 IO_STATUS_BLOCK iosb;
332 UNICODE_STRING name;
333 HANDLE handle;
334 NTSTATUS status;
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
369 __TRY
371 RaiseException( DBG_CONTROL_C, 0, 0, NULL );
373 __EXCEPT_ALL
375 caught_by_dbg = FALSE;
377 __ENDTRY
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 );
389 return 1;
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 );
403 if (!written)
405 SetLastError( ERROR_INVALID_ACCESS );
406 return FALSE;
409 *written = 0;
411 params.mode = CHAR_INFO_MODE_ATTR;
412 params.x = coord.X;
413 params.y = coord.Y;
414 params.count = length;
415 params.wrap = TRUE;
416 params.ch = 0;
417 params.attr = attr;
418 return console_ioctl( handle, IOCTL_CONDRV_FILL_OUTPUT, &params, 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 )
429 WCHAR wch;
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 );
446 if (!written)
448 SetLastError( ERROR_INVALID_ACCESS );
449 return FALSE;
452 *written = 0;
454 params.mode = CHAR_INFO_MODE_TEXT;
455 params.x = coord.X;
456 params.y = coord.Y;
457 params.count = length;
458 params.wrap = TRUE;
459 params.ch = ch;
460 params.attr = 0;
461 return console_ioctl( handle, IOCTL_CONDRV_FILL_OUTPUT, &params, sizeof(params),
462 written, sizeof(written), NULL );
465 HANDLE get_console_wait_handle( HANDLE handle )
467 HANDLE event = 0;
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 );
474 SERVER_END_REQ;
475 if (event)
477 if (InterlockedCompareExchangePointer( &console_wait_event, event, 0 )) NtClose( event );
478 handle = console_wait_event;
480 return handle;
484 /***********************************************************************
485 * FreeConsole (kernelbase.@)
487 BOOL WINAPI DECLSPEC_HOTPATCH FreeConsole(void)
489 HANDLE event;
490 BOOL ret;
492 SERVER_START_REQ( free_console )
494 ret = !wine_server_call_err( req );
496 SERVER_END_REQ;
497 if ((event = InterlockedExchangePointer( &console_wait_event, NULL ))) NtClose( event );
498 return ret;
502 /******************************************************************************
503 * GenerateConsoleCtrlEvent (kernelbase.@)
505 BOOL WINAPI DECLSPEC_HOTPATCH GenerateConsoleCtrlEvent( DWORD event, DWORD group )
507 BOOL ret;
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 );
514 return FALSE;
517 SERVER_START_REQ( send_console_signal )
519 req->signal = event;
520 req->group_id = group;
521 ret = !wine_server_call_err( req );
523 SERVER_END_REQ;
524 return ret;
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 )
537 req->handle = 0;
538 if (!wine_server_call_err( req ))
540 if (reply->input_cp) codepage = reply->input_cp;
543 SERVER_END_REQ;
544 return codepage;
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 ))
556 return FALSE;
558 if (!info)
560 SetLastError( ERROR_INVALID_ACCESS );
561 return FALSE;
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);
567 return TRUE;
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 );
581 return TRUE;
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 );
594 return TRUE;
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 )
616 req->handle = 0;
617 if (!wine_server_call_err( req ))
619 if (reply->output_cp) codepage = reply->output_cp;
622 SERVER_END_REQ;
623 return codepage;
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 ))
636 return FALSE;
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 );
654 return TRUE;
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 );
669 return FALSE;
672 if (!console_ioctl( handle, IOCTL_CONDRV_GET_OUTPUT_INFO, NULL, 0, &condrv_info,
673 sizeof(condrv_info), NULL ))
674 return FALSE;
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) );
690 return TRUE;
694 /******************************************************************************
695 * GetConsoleTitleW (kernelbase.@)
697 DWORD WINAPI DECLSPEC_HOTPATCH GetConsoleTitleW( LPWSTR title, DWORD size )
699 DWORD ret = 0;
701 SERVER_START_REQ( get_console_input_info )
703 req->handle = 0;
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);
708 title[ret] = 0;
711 SERVER_END_REQ;
712 return ret;
716 /***********************************************************************
717 * GetLargestConsoleWindowSize (kernelbase.@)
719 #if defined(__i386__) && !defined(__MINGW32__) && !defined(_MSC_VER)
720 #undef GetLargestConsoleWindowSize
721 DWORD WINAPI DECLSPEC_HOTPATCH GetLargestConsoleWindowSize( HANDLE handle )
723 union {
724 COORD c;
725 DWORD w;
726 } x;
727 x.c = get_largest_console_window_size( handle );
728 return x.w;
731 #else
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 ))
748 return FALSE;
749 *count = info.input_count;
750 return TRUE;
754 /***********************************************************************
755 * PeekConsoleInputA (kernelbase.@)
757 BOOL WINAPI DECLSPEC_HOTPATCH PeekConsoleInputA( HANDLE handle, INPUT_RECORD *buffer,
758 DWORD length, DWORD *count )
760 DWORD read;
762 if (!PeekConsoleInputW( handle, buffer, length, &read )) return FALSE;
763 input_records_WtoA( buffer, read );
764 if (count) *count = read;
765 return TRUE;
769 /***********************************************************************
770 * PeekConsoleInputW (kernelbase.@)
772 BOOL WINAPI DECLSPEC_HOTPATCH PeekConsoleInputW( HANDLE handle, INPUT_RECORD *buffer,
773 DWORD length, DWORD *count )
775 DWORD read;
776 if (!console_ioctl( handle, IOCTL_CONDRV_PEEK, NULL, 0, buffer, length * sizeof(*buffer), &read ))
777 return FALSE;
778 if (count) *count = read / sizeof(*buffer);
779 return TRUE;
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;
790 BOOL ret;
792 TRACE( "(%p,%p,%d,%dx%d,%p)\n", handle, attr, length, coord.X, coord.Y, count );
794 if (!count)
796 SetLastError( ERROR_INVALID_ACCESS );
797 return FALSE;
800 params.mode = CHAR_INFO_MODE_ATTR;
801 params.x = coord.X;
802 params.y = coord.Y;
803 params.width = 0;
804 ret = console_ioctl( handle, IOCTL_CONDRV_READ_OUTPUT, &params, sizeof(params),
805 attr, length * sizeof(*attr), count );
806 *count /= sizeof(*attr);
807 return ret;
811 /******************************************************************************
812 * ReadConsoleOutputCharacterA (kernelbase.@)
814 BOOL WINAPI DECLSPEC_HOTPATCH ReadConsoleOutputCharacterA( HANDLE handle, LPSTR buffer, DWORD length,
815 COORD coord, DWORD *count )
817 DWORD read;
818 BOOL ret;
819 LPWSTR wptr;
821 if (!count)
823 SetLastError( ERROR_INVALID_ACCESS );
824 return FALSE;
827 *count = 0;
828 if (!(wptr = HeapAlloc( GetProcessHeap(), 0, length * sizeof(WCHAR) )))
830 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
831 return FALSE;
833 if ((ret = ReadConsoleOutputCharacterW( handle, wptr, length, coord, &read )))
835 read = WideCharToMultiByte( GetConsoleOutputCP(), 0, wptr, read, buffer, length, NULL, NULL);
836 *count = read;
838 HeapFree( GetProcessHeap(), 0, wptr );
839 return ret;
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;
850 BOOL ret;
852 TRACE( "(%p,%p,%d,%dx%d,%p)\n", handle, buffer, length, coord.X, coord.Y, count );
854 if (!count)
856 SetLastError( ERROR_INVALID_ACCESS );
857 return FALSE;
860 params.mode = CHAR_INFO_MODE_TEXT;
861 params.x = coord.X;
862 params.y = coord.Y;
863 params.width = 0;
864 ret = console_ioctl( handle, IOCTL_CONDRV_READ_OUTPUT, &params, sizeof(params), buffer,
865 length * sizeof(*buffer), count );
866 *count /= sizeof(*buffer);
867 return ret;
871 /******************************************************************************
872 * ReadConsoleOutputA (kernelbase.@)
874 BOOL WINAPI DECLSPEC_HOTPATCH ReadConsoleOutputA( HANDLE handle, CHAR_INFO *buffer, COORD size,
875 COORD coord, SMALL_RECT *region )
877 BOOL ret;
878 int y;
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 );
887 return ret;
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;
898 BOOL ret = TRUE;
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;
913 req->wrap = FALSE;
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 );
922 SERVER_END_REQ;
923 if (!ret) break;
926 region->Bottom = region->Top + height - 1;
927 region->Right = region->Left + width - 1;
928 return ret;
932 /******************************************************************************
933 * ScrollConsoleScreenBufferA (kernelbase.@)
935 BOOL WINAPI DECLSPEC_HOTPATCH ScrollConsoleScreenBufferA( HANDLE handle, SMALL_RECT *scroll,
936 SMALL_RECT *clip, COORD origin, CHAR_INFO *fill )
938 CHAR_INFO ciW;
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,
952 CHAR_INFO *fill )
954 CONSOLE_SCREEN_BUFFER_INFO info;
955 SMALL_RECT dst, clip;
956 int i, j, start = -1;
957 DWORD ret;
958 BOOL inside;
959 COORD src;
961 if (clip_rect)
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 );
966 else
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;
974 src.Y = scroll->Top;
976 /* step 1: get dst rect */
977 dst.Left = origin.X;
978 dst.Top = origin.Y;
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 */
983 if (clip_rect)
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);
990 else
992 clip.Left = 0;
993 clip.Right = info.dwSize.X - 1;
994 clip.Top = 0;
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 );
1009 req->x_src = src.X;
1010 req->y_src = src.Y;
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 );
1017 SERVER_END_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
1025 * outside of clip)
1027 for (j = max(scroll->Top, clip.Top); j <= min(scroll->Bottom, clip.Bottom); j++)
1029 inside = dst.Top <= j && j <= dst.Bottom;
1030 start = -1;
1031 for (i = max(scroll->Left, clip.Left); i <= min(scroll->Right, clip.Right); i++)
1033 if (inside && dst.Left <= i && i <= dst.Right)
1035 if (start != -1)
1037 fill_console_output( handle, start, j, i - start, fill );
1038 start = -1;
1041 else
1043 if (start == -1) start = i;
1046 if (start != -1) fill_console_output( handle, start, j, i - start, fill );
1049 return TRUE;
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 )
1068 BOOL ret;
1070 if (!IsValidCodePage( cp ))
1072 SetLastError( ERROR_INVALID_PARAMETER );
1073 return FALSE;
1075 SERVER_START_REQ( set_console_input_info )
1077 req->handle = 0;
1078 req->mask = SET_CONSOLE_INPUT_INFO_INPUT_CODEPAGE;
1079 req->input_cp = cp;
1080 ret = !wine_server_call_err( req );
1082 SERVER_END_REQ;
1083 return ret;
1087 /******************************************************************************
1088 * SetConsoleCtrlHandler (kernelbase.@)
1090 BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleCtrlHandler( PHANDLER_ROUTINE func, BOOL add )
1092 struct ctrl_handler *handler;
1093 BOOL ret = FALSE;
1095 TRACE( "(%p,%d)\n", func, add );
1097 RtlEnterCriticalSection( &console_section );
1099 if (!func)
1101 if (add) NtCurrentTeb()->Peb->ProcessParameters->ConsoleFlags |= 1;
1102 else NtCurrentTeb()->Peb->ProcessParameters->ConsoleFlags &= ~1;
1103 ret = TRUE;
1105 else if (add)
1107 if ((handler = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*handler) )))
1109 handler->func = func;
1110 handler->next = ctrl_handlers;
1111 ctrl_handlers = handler;
1112 ret = TRUE;
1115 else
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 );
1128 ret = TRUE;
1130 else SetLastError( ERROR_INVALID_PARAMETER );
1133 RtlLeaveCriticalSection( &console_section );
1134 return ret;
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, &params, sizeof(params),
1150 NULL, 0, NULL );
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, &params, sizeof(params), NULL, 0, NULL ))
1168 return FALSE;
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);
1178 do_move = 1;
1180 else if (pos.X > info.srWindow.Right)
1182 info.srWindow.Left = max(pos.X, w) - w + 1;
1183 do_move = 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);
1190 do_move = 1;
1192 else if (pos.Y > info.srWindow.Bottom)
1194 info.srWindow.Top = max(pos.Y, h) - h + 1;
1195 do_move = 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 );
1211 return FALSE;
1213 RtlEnterCriticalSection( &console_section );
1214 MultiByteToWideChar( CP_ACP, 0, name, -1, input_exe, ARRAY_SIZE(input_exe) );
1215 RtlLeaveCriticalSection( &console_section );
1216 return TRUE;
1220 /******************************************************************************
1221 * SetConsoleInputExeNameW (kernelbase.@)
1223 BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleInputExeNameW( LPCWSTR name )
1225 if (!name || !name[0])
1227 SetLastError( ERROR_INVALID_PARAMETER );
1228 return FALSE;
1230 RtlEnterCriticalSection( &console_section );
1231 lstrcpynW( input_exe, name, ARRAY_SIZE(input_exe) );
1232 RtlLeaveCriticalSection( &console_section );
1233 return TRUE;
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 )
1252 BOOL ret;
1254 if (!IsValidCodePage( cp ))
1256 SetLastError( ERROR_INVALID_PARAMETER );
1257 return FALSE;
1259 SERVER_START_REQ( set_console_input_info )
1261 req->handle = 0;
1262 req->mask = SET_CONSOLE_INPUT_INFO_OUTPUT_CODEPAGE;
1263 req->output_cp = cp;
1264 ret = !wine_server_call_err( req );
1266 SERVER_END_REQ;
1267 return ret;
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);
1287 return FALSE;
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, &params, 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, &params, 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, &params, sizeof(params), NULL, 0, NULL );
1335 /******************************************************************************
1336 * SetConsoleTitleW (kernelbase.@)
1338 BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleTitleW( LPCWSTR title )
1340 BOOL ret;
1342 TRACE( "%s\n", debugstr_w( title ));
1343 SERVER_START_REQ( set_console_input_info )
1345 req->handle = 0;
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 );
1350 SERVER_END_REQ;
1351 return ret;
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 );
1365 if (!absolute)
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, &params, 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;
1391 BOOL ret;
1393 if (count > 0)
1395 if (!buffer)
1397 SetLastError( ERROR_INVALID_ACCESS );
1398 return FALSE;
1400 if (!(recW = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*recW) )))
1402 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1403 return FALSE;
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 );
1410 return ret;
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 );
1425 return FALSE;
1428 if (!DeviceIoControl( handle, IOCTL_CONDRV_WRITE_INPUT, (void *)buffer, count * sizeof(*buffer), NULL, 0, NULL, NULL ))
1429 return FALSE;
1431 if (!written)
1433 SetLastError( ERROR_INVALID_ACCESS );
1434 return FALSE;
1436 *written = count;
1437 return TRUE;
1441 /***********************************************************************
1442 * WriteConsoleOutputA (kernelbase.@)
1444 BOOL WINAPI DECLSPEC_HOTPATCH WriteConsoleOutputA( HANDLE handle, const CHAR_INFO *buffer,
1445 COORD size, COORD coord, SMALL_RECT *region )
1447 int y;
1448 BOOL ret;
1449 COORD new_size, new_coord;
1450 CHAR_INFO *ciW;
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;
1459 return TRUE;
1462 /* only copy the useful rectangle */
1463 if (!(ciW = HeapAlloc( GetProcessHeap(), 0, sizeof(CHAR_INFO) * new_size.X * new_size.Y )))
1464 return FALSE;
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 );
1472 return ret;
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;
1484 size_t params_size;
1485 BOOL ret;
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 );
1494 return FALSE;
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 );
1506 return FALSE;
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 );
1519 return ret;
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;
1530 size_t size;
1531 BOOL ret;
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 );
1538 return FALSE;
1541 *written = 0;
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;
1547 params->width = 0;
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 );
1551 return ret;
1555 /******************************************************************************
1556 * WriteConsoleOutputCharacterA (kernelbase.@)
1558 BOOL WINAPI DECLSPEC_HOTPATCH WriteConsoleOutputCharacterA( HANDLE handle, LPCSTR str, DWORD length,
1559 COORD coord, DWORD *written )
1561 BOOL ret;
1562 LPWSTR strW = NULL;
1563 DWORD lenW = 0;
1565 TRACE( "(%p,%s,%d,%dx%d,%p)\n", handle, debugstr_an(str, length), length, coord.X, coord.Y, written );
1567 if (length > 0)
1569 UINT cp = GetConsoleOutputCP();
1570 if (!str)
1572 SetLastError( ERROR_INVALID_ACCESS );
1573 return FALSE;
1575 lenW = MultiByteToWideChar( cp, 0, str, length, NULL, 0 );
1577 if (!(strW = HeapAlloc( GetProcessHeap(), 0, lenW * sizeof(WCHAR) )))
1579 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1580 return FALSE;
1582 MultiByteToWideChar( cp, 0, str, length, strW, lenW );
1584 ret = WriteConsoleOutputCharacterW( handle, strW, lenW, coord, written );
1585 HeapFree( GetProcessHeap(), 0, strW );
1586 return ret;
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;
1597 size_t size;
1598 BOOL ret;
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 );
1605 return FALSE;
1608 *written = 0;
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;
1614 params->width = 0;
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 );
1618 return ret;