From: Hugh McMaster hugh.mcmaster@outlook.com
--- dlls/kernel32/tests/console.c | 6 +++--- dlls/kernelbase/console.c | 28 +++++++++++++++++++--------- include/wine/condrv.h | 7 +++++++ programs/conhost/conhost.c | 12 ++++++++---- 4 files changed, 37 insertions(+), 16 deletions(-)
diff --git a/dlls/kernel32/tests/console.c b/dlls/kernel32/tests/console.c index b10254bc161..c145aa4cb59 100644 --- a/dlls/kernel32/tests/console.c +++ b/dlls/kernel32/tests/console.c @@ -4272,12 +4272,12 @@ static void test_GetConsoleTitleW(void)
ret = GetConsoleTitleW(buf, ARRAY_SIZE(buf)); ok(ret, "GetConsoleTitleW failed: %lu\n", GetLastError()); - todo_wine ok(ret == wcslen(str), "Got string length %lu, expected %Iu\n", ret, wcslen(str)); + ok(ret == wcslen(str), "Got string length %lu, expected %Iu\n", ret, wcslen(str)); ok(!wcscmp(buf, str), "Title = %s\n", wine_dbgstr_w(buf));
ret = GetConsoleTitleW(buf, 2); ok(ret, "GetConsoleTitleW failed: %lu\n", GetLastError()); - todo_wine ok(ret == wcslen(str), "Got string length %lu, expected %Iu\n", ret, wcslen(str)); + ok(ret == wcslen(str), "Got string length %lu, expected %Iu\n", ret, wcslen(str)); if (!skip_nt) ok(!wcscmp(buf, L"t"), "Title = %s\n", wine_dbgstr_w(buf));
ret = GetConsoleTitleW(buf, 4); @@ -4289,7 +4289,7 @@ static void test_GetConsoleTitleW(void) ok(ret, "SetConsoleTitleW failed: %lu\n", GetLastError());
ret = GetConsoleTitleW(buf, ARRAY_SIZE(buf)); - todo_wine ok(!ret, "Unexpected string length; error %lu\n", GetLastError()); + ok(!ret, "Unexpected string length; error %lu\n", GetLastError()); }
static void test_file_info(HANDLE input, HANDLE output) diff --git a/dlls/kernelbase/console.c b/dlls/kernelbase/console.c index 590198cf7bf..434399b073a 100644 --- a/dlls/kernelbase/console.c +++ b/dlls/kernelbase/console.c @@ -1012,12 +1012,11 @@ DWORD WINAPI DECLSPEC_HOTPATCH GetConsoleTitleA( LPSTR title, DWORD size ) DWORD ret;
if (!ptr) return 0; + ret = GetConsoleTitleW( ptr, size ); if (ret) - { - WideCharToMultiByte( GetConsoleOutputCP(), 0, ptr, ret + 1, title, size, NULL, NULL); - ret = strlen(title); - } + WideCharToMultiByte( GetConsoleOutputCP(), 0, ptr, -1, title, size, NULL, NULL); + HeapFree( GetProcessHeap(), 0, ptr ); return ret; } @@ -1028,15 +1027,26 @@ DWORD WINAPI DECLSPEC_HOTPATCH GetConsoleTitleA( LPSTR title, DWORD size ) */ DWORD WINAPI DECLSPEC_HOTPATCH GetConsoleTitleW( LPWSTR title, DWORD size ) { - if (!size) return 0; + struct condrv_title_params *params; + size_t max_size = sizeof(*params) + (size - 1) * sizeof(WCHAR); + + if (!title || !size) return 0; + + if (!(params = HeapAlloc( GetProcessHeap(), 0, max_size ))) + return 0;
if (!console_ioctl( RtlGetCurrentPeb()->ProcessParameters->ConsoleHandle, IOCTL_CONDRV_GET_TITLE, - NULL, 0, title, (size - 1) * sizeof(WCHAR), &size )) + NULL, 0, params, max_size, &size )) return 0;
- size /= sizeof(WCHAR); - title[size] = 0; - return size + 1; + if (size < sizeof(*params)) return 0; + + size -= sizeof(*params); + memcpy( title, params->buffer, size ); + title[ size / sizeof(WCHAR) ] = 0; + size = params->title_len; + HeapFree( GetProcessHeap(), 0, params ); + return size; }
diff --git a/include/wine/condrv.h b/include/wine/condrv.h index 3355d7177b0..51534720444 100644 --- a/include/wine/condrv.h +++ b/include/wine/condrv.h @@ -159,6 +159,13 @@ struct condrv_output_info_params #define SET_CONSOLE_OUTPUT_INFO_POPUP_ATTR 0x0040 #define SET_CONSOLE_OUTPUT_INFO_FONT 0x0080
+/* IOCTL_CONDRV_GET_TITLE params */ +struct condrv_title_params +{ + unsigned int title_len; + WCHAR buffer[1]; +}; + /* IOCTL_CONDRV_FILL_OUTPUT params */ struct condrv_fill_output_params { diff --git a/programs/conhost/conhost.c b/programs/conhost/conhost.c index 792daeb520f..c3a106c9321 100644 --- a/programs/conhost/conhost.c +++ b/programs/conhost/conhost.c @@ -2675,12 +2675,16 @@ static NTSTATUS console_input_ioctl( struct console *console, unsigned int code,
case IOCTL_CONDRV_GET_TITLE: { - WCHAR *result; + size_t title_len, str_size; + struct condrv_title_params *params; if (in_size) return STATUS_INVALID_PARAMETER; + title_len = console->title ? wcslen( console->title ) : 0; + str_size = min( *out_size - sizeof(*params), title_len * sizeof(WCHAR) ); + *out_size = sizeof(*params) + str_size; + if (!(params = alloc_ioctl_buffer( *out_size ))) return STATUS_NO_MEMORY; TRACE( "returning title %s\n", debugstr_w(console->title) ); - *out_size = min( *out_size, console->title ? wcslen( console->title ) * sizeof(WCHAR) : 0 ); - if (!(result = alloc_ioctl_buffer( *out_size ))) return STATUS_NO_MEMORY; - if (*out_size) memcpy( result, console->title, *out_size ); + if (str_size) memcpy( params->buffer, console->title, str_size ); + params->title_len = title_len; return STATUS_SUCCESS; }