From 27df7f518caa237cd629e26131dbd23b1685c4d8 Mon Sep 17 00:00:00 2001 From: Hugh McMaster Date: Wed, 9 Feb 2022 20:43:54 +0100 Subject: [PATCH] kernelbase: Implement SetCurrentConsoleFontEx. Signed-off-by: Hugh McMaster Signed-off-by: Jacek Caban Signed-off-by: Alexandre Julliard --- dlls/kernel32/console.c | 7 ------ dlls/kernel32/kernel32.spec | 2 +- dlls/kernel32/tests/console.c | 40 ++++++++++++++++----------------- dlls/kernelbase/console.c | 36 +++++++++++++++++++++++++++++ dlls/kernelbase/kernelbase.spec | 1 + include/wine/condrv.h | 1 + programs/conhost/conhost.c | 25 ++++++++++++++++++--- programs/conhost/conhost.h | 14 +++++++----- programs/conhost/window.c | 28 ++++++++++++++--------- 9 files changed, 108 insertions(+), 46 deletions(-) diff --git a/dlls/kernel32/console.c b/dlls/kernel32/console.c index 80f3419cd7a..58bd18d2a5f 100644 --- a/dlls/kernel32/console.c +++ b/dlls/kernel32/console.c @@ -480,10 +480,3 @@ BOOL WINAPI GetConsoleFontInfo(HANDLE hConsole, BOOL maximize, DWORD numfonts, C SetLastError(LOWORD(E_NOTIMPL) /* win10 1709+ */); return FALSE; } - -BOOL WINAPI SetCurrentConsoleFontEx(HANDLE hConsole, BOOL maxwindow, CONSOLE_FONT_INFOEX *cfix) -{ - FIXME("(%p %d %p): stub!\n", hConsole, maxwindow, cfix); - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; -} diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index 87fa0c39381..6e063bfaa7b 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -1390,7 +1390,7 @@ @ stdcall -import SetConsoleTitleW(wstr) @ stdcall -import SetConsoleWindowInfo(long long ptr) @ stdcall SetCriticalSectionSpinCount(ptr long) NTDLL.RtlSetCriticalSectionSpinCount -@ stdcall SetCurrentConsoleFontEx(long long ptr) +@ stdcall -import SetCurrentConsoleFontEx(long long ptr) @ stdcall -import SetCurrentDirectoryA(str) @ stdcall -import SetCurrentDirectoryW(wstr) @ stub SetDaylightFlag diff --git a/dlls/kernel32/tests/console.c b/dlls/kernel32/tests/console.c index e4d9d43f4c4..5443a611f80 100644 --- a/dlls/kernel32/tests/console.c +++ b/dlls/kernel32/tests/console.c @@ -3576,18 +3576,18 @@ static void test_SetCurrentConsoleFontEx(HANDLE std_output) SetLastError(0xdeadbeef); ret = SetCurrentConsoleFontEx(NULL, FALSE, &cfix); ok(!ret, "got %d, expected 0\n", ret); - todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError()); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError()); SetLastError(0xdeadbeef); ret = SetCurrentConsoleFontEx(NULL, TRUE, &cfix); ok(!ret, "got %d, expected 0\n", ret); - todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError()); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError()); CreatePipe(&pipe1, &pipe2, NULL, 0); SetLastError(0xdeadbeef); ret = SetCurrentConsoleFontEx(pipe1, FALSE, &cfix); ok(!ret, "got %d, expected 0\n", ret); - todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError()); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError()); CloseHandle(pipe1); CloseHandle(pipe2); @@ -3595,47 +3595,47 @@ static void test_SetCurrentConsoleFontEx(HANDLE std_output) SetLastError(0xdeadbeef); ret = SetCurrentConsoleFontEx(pipe1, TRUE, &cfix); ok(!ret, "got %d, expected 0\n", ret); - todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError()); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError()); CloseHandle(pipe1); CloseHandle(pipe2); SetLastError(0xdeadbeef); ret = SetCurrentConsoleFontEx(std_input, FALSE, &cfix); ok(!ret, "got %d, expected 0\n", ret); - todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError()); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError()); SetLastError(0xdeadbeef); ret = SetCurrentConsoleFontEx(std_input, TRUE, &cfix); ok(!ret, "got %d, expected 0\n", ret); - todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError()); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError()); SetLastError(0xdeadbeef); ret = SetCurrentConsoleFontEx(std_output, FALSE, &cfix); ok(!ret, "got %d, expected 0\n", ret); - todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError()); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError()); SetLastError(0xdeadbeef); ret = SetCurrentConsoleFontEx(std_output, TRUE, &cfix); ok(!ret, "got %d, expected 0\n", ret); - todo_wine ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError()); + ok(GetLastError() == ERROR_INVALID_PARAMETER, "got %u, expected 87\n", GetLastError()); cfix = orig_cfix; SetLastError(0xdeadbeef); ret = SetCurrentConsoleFontEx(NULL, FALSE, &cfix); ok(!ret, "got %d, expected 0\n", ret); - todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); + ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); SetLastError(0xdeadbeef); ret = SetCurrentConsoleFontEx(NULL, TRUE, &cfix); ok(!ret, "got %d, expected 0\n", ret); - todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); + ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); CreatePipe(&pipe1, &pipe2, NULL, 0); SetLastError(0xdeadbeef); ret = SetCurrentConsoleFontEx(pipe1, FALSE, &cfix); ok(!ret, "got %d, expected 0\n", ret); - todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); + ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); CloseHandle(pipe1); CloseHandle(pipe2); @@ -3643,35 +3643,35 @@ static void test_SetCurrentConsoleFontEx(HANDLE std_output) SetLastError(0xdeadbeef); ret = SetCurrentConsoleFontEx(pipe1, TRUE, &cfix); ok(!ret, "got %d, expected 0\n", ret); - todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); + ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); CloseHandle(pipe1); CloseHandle(pipe2); SetLastError(0xdeadbeef); ret = SetCurrentConsoleFontEx(std_input, FALSE, &cfix); ok(!ret, "got %d, expected 0\n", ret); - todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); + ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); SetLastError(0xdeadbeef); ret = SetCurrentConsoleFontEx(std_input, TRUE, &cfix); ok(!ret, "got %d, expected 0\n", ret); - todo_wine ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); + ok(GetLastError() == ERROR_INVALID_HANDLE, "got %u, expected 6\n", GetLastError()); SetLastError(0xdeadbeef); ret = SetCurrentConsoleFontEx(std_output, FALSE, &cfix); - todo_wine ok(ret, "got %d, expected non-zero\n", ret); - todo_wine ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError()); + ok(ret, "got %d, expected non-zero\n", ret); + ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError()); SetLastError(0xdeadbeef); ret = SetCurrentConsoleFontEx(std_output, TRUE, &cfix); - todo_wine ok(ret, "got %d, expected non-zero\n", ret); - todo_wine ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError()); + ok(ret, "got %d, expected non-zero\n", ret); + ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError()); /* Restore original console font parameters */ SetLastError(0xdeadbeef); ret = SetCurrentConsoleFontEx(std_output, FALSE, &orig_cfix); - todo_wine ok(ret, "got %d, expected non-zero\n", ret); - todo_wine ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError()); + ok(ret, "got %d, expected non-zero\n", ret); + ok(GetLastError() == 0xdeadbeef, "got %u, expected 0xdeadbeef\n", GetLastError()); } static void test_GetConsoleFontSize(HANDLE std_output) diff --git a/dlls/kernelbase/console.c b/dlls/kernelbase/console.c index a7eeb439232..b81328f705d 100644 --- a/dlls/kernelbase/console.c +++ b/dlls/kernelbase/console.c @@ -1303,6 +1303,42 @@ BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleWindowInfo( HANDLE handle, BOOL absolute } +/****************************************************************************** + * SetCurrentConsoleFontEx (kernelbase.@) + */ +BOOL WINAPI SetCurrentConsoleFontEx( HANDLE handle, BOOL maxwindow, CONSOLE_FONT_INFOEX *info ) +{ + struct + { + struct condrv_output_info_params params; + WCHAR face_name[LF_FACESIZE]; + } data; + + size_t size; + + TRACE( "(%p %d %p)\n", handle, maxwindow, info ); + + if (info->cbSize != sizeof(*info)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + data.params.mask = SET_CONSOLE_OUTPUT_INFO_FONT; + + data.params.info.font_width = info->dwFontSize.X; + data.params.info.font_height = info->dwFontSize.Y; + data.params.info.font_pitch_family = info->FontFamily; + data.params.info.font_weight = info->FontWeight; + + size = wcsnlen( info->FaceName, LF_FACESIZE - 1 ) * sizeof(WCHAR); + memcpy( data.face_name, info->FaceName, size ); + + size += sizeof(struct condrv_output_info_params); + return console_ioctl( handle, IOCTL_CONDRV_SET_OUTPUT_INFO, &data, size, NULL, 0, NULL ); +} + + /*********************************************************************** * ReadConsoleInputA (kernelbase.@) */ diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index 01135d6250a..91c4909e006 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -1422,6 +1422,7 @@ @ stdcall SetConsoleTitleW(wstr) @ stdcall SetConsoleWindowInfo(long long ptr) @ stdcall SetCriticalSectionSpinCount(ptr long) ntdll.RtlSetCriticalSectionSpinCount +@ stdcall SetCurrentConsoleFontEx(long long ptr) @ stdcall SetCurrentDirectoryA(str) @ stdcall SetCurrentDirectoryW(wstr) @ stdcall SetDefaultDllDirectories(long) diff --git a/include/wine/condrv.h b/include/wine/condrv.h index 4d2332a1ee9..b5e294b9401 100644 --- a/include/wine/condrv.h +++ b/include/wine/condrv.h @@ -155,6 +155,7 @@ struct condrv_output_info_params #define SET_CONSOLE_OUTPUT_INFO_DISPLAY_WINDOW 0x0010 #define SET_CONSOLE_OUTPUT_INFO_MAX_SIZE 0x0020 #define SET_CONSOLE_OUTPUT_INFO_POPUP_ATTR 0x0040 +#define SET_CONSOLE_OUTPUT_INFO_FONT 0x0080 /* IOCTL_CONDRV_FILL_OUTPUT params */ struct condrv_fill_output_params diff --git a/programs/conhost/conhost.c b/programs/conhost/conhost.c index 2b137c40fb0..8b03d749d21 100644 --- a/programs/conhost/conhost.c +++ b/programs/conhost/conhost.c @@ -1830,7 +1830,7 @@ NTSTATUS change_screen_buffer_size( struct screen_buffer *screen_buffer, int new } static NTSTATUS set_output_info( struct screen_buffer *screen_buffer, - const struct condrv_output_info_params *params ) + const struct condrv_output_info_params *params, size_t in_size ) { const struct condrv_output_info *info = ¶ms->info; NTSTATUS status; @@ -1917,6 +1917,24 @@ static NTSTATUS set_output_info( struct screen_buffer *screen_buffer, screen_buffer->max_width = info->max_width; screen_buffer->max_height = info->max_height; } + if (params->mask & SET_CONSOLE_OUTPUT_INFO_FONT) + { + WCHAR *face_name = (WCHAR *)(params + 1); + size_t face_name_size = in_size - sizeof(*params); + unsigned int height = info->font_height; + unsigned int weight = FW_NORMAL; + + if (!face_name_size) + { + face_name = screen_buffer->font.face_name; + face_name_size = screen_buffer->font.face_len * sizeof(WCHAR); + } + + if (!height) height = 12; + if (info->font_weight >= FW_SEMIBOLD) weight = FW_BOLD; + + update_console_font( screen_buffer->console, face_name, face_name_size, height, weight ); + } if (is_active( screen_buffer )) { @@ -2429,8 +2447,9 @@ static NTSTATUS screen_buffer_ioctl( struct screen_buffer *screen_buffer, unsign return get_output_info( screen_buffer, out_size ); case IOCTL_CONDRV_SET_OUTPUT_INFO: - if (in_size != sizeof(struct condrv_output_info_params) || *out_size) return STATUS_INVALID_PARAMETER; - return set_output_info( screen_buffer, in_data ); + if (in_size < sizeof(struct condrv_output_info_params) || *out_size) + return STATUS_INVALID_PARAMETER; + return set_output_info( screen_buffer, in_data, in_size ); case IOCTL_CONDRV_FILL_OUTPUT: if (in_size != sizeof(struct condrv_fill_output_params) || *out_size != sizeof(DWORD)) diff --git a/programs/conhost/conhost.h b/programs/conhost/conhost.h index 5e9b999380c..3cbd2ed2d80 100644 --- a/programs/conhost/conhost.h +++ b/programs/conhost/conhost.h @@ -130,17 +130,21 @@ struct screen_buffer struct wine_rb_entry entry; /* map entry */ }; -BOOL init_window( struct console *console ); -void init_message_window( struct console *console ); -void update_window_region( struct console *console, const RECT *update ); -void update_window_config( struct console *console, BOOL delay ); - +/* conhost.c */ NTSTATUS write_console_input( struct console *console, const INPUT_RECORD *records, unsigned int count, BOOL flush ); void notify_screen_buffer_size( struct screen_buffer *screen_buffer ); NTSTATUS change_screen_buffer_size( struct screen_buffer *screen_buffer, int new_width, int new_height ); +/* window.c */ +void update_console_font( struct console *console, const WCHAR *face_name, size_t face_name_size, + unsigned int height, unsigned int weight ); +BOOL init_window( struct console *console ); +void init_message_window( struct console *console ); +void update_window_region( struct console *console, const RECT *update ); +void update_window_config( struct console *console, BOOL delay ); + static inline void empty_update_rect( struct screen_buffer *screen_buffer, RECT *rect ) { SetRect( rect, screen_buffer->width, screen_buffer->height, 0, 0 ); diff --git a/programs/conhost/window.c b/programs/conhost/window.c index db04ba120e4..33ffb3915ed 100644 --- a/programs/conhost/window.c +++ b/programs/conhost/window.c @@ -652,7 +652,8 @@ static HFONT select_font_config( struct console_config *config, unsigned int cp, return font; } -static void fill_logfont( LOGFONTW *lf, const WCHAR *name, unsigned int height, unsigned int weight ) +static void fill_logfont( LOGFONTW *lf, const WCHAR *face_name, size_t face_name_size, + unsigned int height, unsigned int weight ) { lf->lfHeight = height; lf->lfWidth = 0; @@ -667,7 +668,9 @@ static void fill_logfont( LOGFONTW *lf, const WCHAR *name, unsigned int height, lf->lfClipPrecision = CLIP_DEFAULT_PRECIS; lf->lfQuality = DEFAULT_QUALITY; lf->lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE; - lstrcpyW( lf->lfFaceName, name ); + face_name_size = min( face_name_size, sizeof(lf->lfFaceName) - sizeof(WCHAR) ); + memcpy( lf->lfFaceName, face_name, face_name_size ); + lf->lfFaceName[face_name_size / sizeof(WCHAR)] = 0; } static BOOL set_console_font( struct console *console, const LOGFONTW *logfont ) @@ -705,6 +708,7 @@ static BOOL set_console_font( struct console *console, const LOGFONTW *logfont ) font_info->width = tm.tmAveCharWidth; font_info->height = tm.tmHeight + tm.tmExternalLeading; + font_info->pitch_family = tm.tmPitchAndFamily; font_info->weight = tm.tmWeight; free( font_info->face_name ); @@ -851,15 +855,15 @@ static int WINAPI get_first_font_enum( const LOGFONTW *lf, const TEXTMETRICW *tm /* sets logfont as the new font for the console */ -static void update_console_font( struct console *console, const WCHAR *font, - unsigned int height, unsigned int weight ) +void update_console_font( struct console *console, const WCHAR *face_name, size_t face_name_size, + unsigned int height, unsigned int weight ) { struct font_chooser fc; LOGFONTW lf; - if (font[0] && height && weight) + if (face_name[0] && height && weight) { - fill_logfont( &lf, font, height, weight ); + fill_logfont( &lf, face_name, face_name_size, height, weight ); if (set_console_font( console, &lf )) return; } @@ -1581,8 +1585,9 @@ static BOOL select_font( struct dialog_info *di ) if (font_idx < 0 || size_idx < 0 || size_idx >= di->font_count) return FALSE; - fill_logfont( &lf, di->font[size_idx].faceName, di->font[size_idx].height, - di->font[size_idx].weight ); + fill_logfont( &lf, di->font[size_idx].faceName, + wcslen(di->font[size_idx].faceName) * sizeof(WCHAR), + di->font[size_idx].height, di->font[size_idx].weight ); font = select_font_config( &config, di->console->output_cp, di->console->win, &lf ); if (!font) return FALSE; @@ -1702,7 +1707,9 @@ static INT_PTR WINAPI font_dialog_proc( HWND dialog, UINT msg, WPARAM wparam, LP { LOGFONTW lf; - fill_logfont( &lf, di->font[val].faceName, di->font[val].height, di->font[val].weight ); + fill_logfont( &lf, di->font[val].faceName, + wcslen(di->font[val].faceName) * sizeof(WCHAR), + di->font[val].height, di->font[val].weight ); DeleteObject( select_font_config( &di->config, di->console->output_cp, di->console->win, &lf )); } @@ -1901,7 +1908,8 @@ static void apply_config( struct console *console, const struct console_config * memcmp( console->active->font.face_name, config->face_name, console->active->font.face_len * sizeof(WCHAR) )) { - update_console_font( console, config->face_name, config->cell_height, config->font_weight ); + update_console_font( console, config->face_name, wcslen(config->face_name) * sizeof(WCHAR), + config->cell_height, config->font_weight ); } update_window( console );