Signed-off-by: Hugh McMaster hugh.mcmaster@outlook.com --- dlls/kernel32/console.c | 7 ------- dlls/kernel32/kernel32.spec | 2 +- dlls/kernel32/tests/console.c | 30 +++++++++++++------------- dlls/kernelbase/console.c | 37 +++++++++++++++++++++++++++++++++ dlls/kernelbase/kernelbase.spec | 1 + include/wine/condrv.h | 6 ++++++ programs/conhost/conhost.c | 9 +++++++- programs/conhost/conhost.h | 14 ++++++++----- programs/conhost/window.c | 5 +++-- 9 files changed, 80 insertions(+), 31 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..0943a318f6a 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,36 +3595,36 @@ 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); @@ -3635,7 +3635,7 @@ static void test_SetCurrentConsoleFontEx(HANDLE std_output) 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);
@@ -3650,7 +3650,7 @@ static void test_SetCurrentConsoleFontEx(HANDLE std_output) 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); @@ -3659,8 +3659,8 @@ static void test_SetCurrentConsoleFontEx(HANDLE std_output)
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); @@ -3670,8 +3670,8 @@ static void test_SetCurrentConsoleFontEx(HANDLE std_output) /* 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..0501e140a03 100644 --- a/dlls/kernelbase/console.c +++ b/dlls/kernelbase/console.c @@ -1303,6 +1303,43 @@ BOOL WINAPI DECLSPEC_HOTPATCH SetConsoleWindowInfo( HANDLE handle, BOOL absolute }
+/****************************************************************************** + * SetCurrentConsoleFontEx (kernelbase.@) + */ +BOOL WINAPI SetCurrentConsoleFontEx(HANDLE hConsole, BOOL maxwindow, CONSOLE_FONT_INFOEX *cfix) +{ + struct condrv_output_info_params_font data; + + TRACE( "(%p %d %p)\n", hConsole, maxwindow, cfix ); + + if (cfix->cbSize != sizeof(CONSOLE_FONT_INFOEX)) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + if (maxwindow) + { + FIXME( "(%p %d %p): semi-stub\n", hConsole, maxwindow, cfix); + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + return FALSE; + } + + data.params.mask = SET_CONSOLE_OUTPUT_INFO_FONT; + + data.params.info.font_width = cfix->dwFontSize.X; + data.params.info.font_height = cfix->dwFontSize.Y; + data.params.info.font_pitch_family = cfix->FontFamily; + data.params.info.font_weight = cfix->FontWeight; + + memcpy( data.face_name, cfix->FaceName, sizeof(cfix->FaceName) ); + data.face_name[ LF_FACESIZE - 1 ] = 0; + + return console_ioctl( hConsole, IOCTL_CONDRV_SET_OUTPUT_INFO, + &data, sizeof(data), 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..605e6f2c2fe 100644 --- a/include/wine/condrv.h +++ b/include/wine/condrv.h @@ -148,6 +148,11 @@ struct condrv_output_info_params struct condrv_output_info info; /* output info */ };
+struct condrv_output_info_params_font { + struct condrv_output_info_params params; + WCHAR face_name[LF_FACESIZE]; +}; + #define SET_CONSOLE_OUTPUT_INFO_CURSOR_GEOM 0x0001 #define SET_CONSOLE_OUTPUT_INFO_CURSOR_POS 0x0002 #define SET_CONSOLE_OUTPUT_INFO_SIZE 0x0004 @@ -155,6 +160,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 78f6e345170..456f3a4889e 100644 --- a/programs/conhost/conhost.c +++ b/programs/conhost/conhost.c @@ -1913,6 +1913,13 @@ 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); + + update_console_font( screen_buffer->console, face_name, + info->font_height, info->font_weight ); + }
if (is_active( screen_buffer )) { @@ -2425,7 +2432,7 @@ 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; + if (in_size < sizeof(struct condrv_output_info) || *out_size) return STATUS_INVALID_PARAMETER; return set_output_info( screen_buffer, in_data );
case IOCTL_CONDRV_FILL_OUTPUT: diff --git a/programs/conhost/conhost.h b/programs/conhost/conhost.h index 5e9b999380c..88a26f70fd0 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 *font, + 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 7ad0d48effd..0d450774d23 100644 --- a/programs/conhost/window.c +++ b/programs/conhost/window.c @@ -705,6 +705,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,8 +852,8 @@ 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 *font, + unsigned int height, unsigned int weight ) { struct font_chooser fc; LOGFONTW lf;
Hi Hugh,
On 2/2/22 12:10, Hugh McMaster wrote:
+struct condrv_output_info_params_font {
- struct condrv_output_info_params params;
- WCHAR face_name[LF_FACESIZE];
+};
Since you use it only for SetCurrentConsoleFontEx, you could just move it there. See how GetCurrentConsoleFontEx is handling it. Also, ioclt() size should probably only contain meaningful bytes (no extra uninitialized LF_FACESIZE bytes and no null-byte). On conhost side, we can calculate string length from params size.
#define SET_CONSOLE_OUTPUT_INFO_CURSOR_GEOM 0x0001 #define SET_CONSOLE_OUTPUT_INFO_CURSOR_POS 0x0002 #define SET_CONSOLE_OUTPUT_INFO_SIZE 0x0004 @@ -155,6 +160,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 78f6e345170..456f3a4889e 100644 --- a/programs/conhost/conhost.c +++ b/programs/conhost/conhost.c @@ -1913,6 +1913,13 @@ 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);
update_console_font( screen_buffer->console, face_name,
info->font_height, info->font_weight );
- }
Looking at update_console_font, if creating a font with passed arguments fails, it will set a first found font, ignoring all passed arguments. Should it return a failure instead?
Thanks,
Jacek
Hi Jacek,
Thanks for the review.
On Sat, 5 Feb 2022 at 04:29, Jacek Caban wrote:
Hi Hugh,
On 2/2/22 12:10, Hugh McMaster wrote:
+struct condrv_output_info_params_font {
- struct condrv_output_info_params params;
- WCHAR face_name[LF_FACESIZE];
+};
Since you use it only for SetCurrentConsoleFontEx, you could just move it there. See how GetCurrentConsoleFontEx is handling it.
We could use the struct for GetCurrentConsoleFontEx too, but it doesn't really matter.
Also, ioclt() size should probably only contain meaningful bytes (no extra uninitialized LF_FACESIZE bytes and no null-byte). On conhost side, we can calculate string length from params size.
#define SET_CONSOLE_OUTPUT_INFO_CURSOR_GEOM 0x0001 #define SET_CONSOLE_OUTPUT_INFO_CURSOR_POS 0x0002 #define SET_CONSOLE_OUTPUT_INFO_SIZE 0x0004 @@ -155,6 +160,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 78f6e345170..456f3a4889e 100644 --- a/programs/conhost/conhost.c +++ b/programs/conhost/conhost.c @@ -1913,6 +1913,13 @@ 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);
update_console_font( screen_buffer->console, face_name,
info->font_height, info->font_weight );
- }
Looking at update_console_font, if creating a font with passed arguments fails, it will set a first found font, ignoring all passed arguments. Should it return a failure instead?
SetCurrentConsoleFontEx only ever fails if the console output handle is invalid. If it can't match all parameters, it just sets the closest possible font.
When testing various font parameters, I saw the following behaviour: - Font height of 0 returned a font height of 12 on all testbot VMs. It's not clear where the 12 comes from. - Font weight of 0 (invalid) to 500 returned FW_NORMAL, and 600 to 900 returned FW_BOLD. - Font family of 0 returned various defaults, 48 or 54. - Empty or invalid font face returned either Terminal or a TrueType font. It's not clear how the font face is chosen. It might be due to a registry setting.
I think we should leave the font face and font family as they are if we encounter those edge cases. We can handle the font height and weight cases though.