From: Jacek Caban Subject: [PATCH 1/4] kernelbase: Invalidate console wait handle in FreeConsole. Message-Id: <2de19e39-ca8e-67d4-2284-b25170c0e4f0@codeweavers.com> Date: Wed, 1 Jul 2020 16:27:05 +0200 Signed-off-by: Jacek Caban --- That's how kernel32 handles it. I think this will need to be reimplemented, but to do it incrementally, it would be very useful to have alloc, free and attach console functionality in one place first. dlls/kernelbase/console.c | 22 ++++++++++++++++++++++ dlls/kernelbase/kernelbase.h | 1 + dlls/kernelbase/sync.c | 20 +------------------- 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/dlls/kernelbase/console.c b/dlls/kernelbase/console.c index 5fb84c0bd9..bd927c9b83 100644 --- a/dlls/kernelbase/console.c +++ b/dlls/kernelbase/console.c @@ -53,6 +53,8 @@ static CRITICAL_SECTION_DEBUG critsect_debug = }; static CRITICAL_SECTION console_section = { &critsect_debug, -1, 0, 0, 0, 0 }; +static HANDLE console_wait_event; + static WCHAR input_exe[MAX_PATH + 1]; struct ctrl_handler @@ -345,12 +347,31 @@ BOOL WINAPI DECLSPEC_HOTPATCH FillConsoleOutputCharacterW( HANDLE handle, WCHAR return ret; } +HANDLE get_console_wait_handle( HANDLE handle ) +{ + HANDLE event = 0; + + SERVER_START_REQ( get_console_wait_event ) + { + req->handle = wine_server_obj_handle( console_handle_map( handle )); + if (!wine_server_call( req )) event = wine_server_ptr_handle( reply->event ); + } + SERVER_END_REQ; + if (event) + { + if (InterlockedCompareExchangePointer( &console_wait_event, event, 0 )) NtClose( event ); + handle = console_wait_event; + } + return handle; +} + /*********************************************************************** * FreeConsole (kernelbase.@) */ BOOL WINAPI DECLSPEC_HOTPATCH FreeConsole(void) { + HANDLE event; BOOL ret; SERVER_START_REQ( free_console ) @@ -358,6 +379,7 @@ BOOL WINAPI DECLSPEC_HOTPATCH FreeConsole(void) ret = !wine_server_call_err( req ); } SERVER_END_REQ; + if ((event = InterlockedExchangePointer( &console_wait_event, NULL ))) NtClose( event ); return ret; } diff --git a/dlls/kernelbase/kernelbase.h b/dlls/kernelbase/kernelbase.h index 88765df3d1..9fb4434fbb 100644 --- a/dlls/kernelbase/kernelbase.h +++ b/dlls/kernelbase/kernelbase.h @@ -28,6 +28,7 @@ extern WCHAR *file_name_AtoW( LPCSTR name, BOOL alloc ) DECLSPEC_HIDDEN; extern DWORD file_name_WtoA( LPCWSTR src, INT srclen, LPSTR dest, INT destlen ) DECLSPEC_HIDDEN; extern void init_startup_info( RTL_USER_PROCESS_PARAMETERS *params ) DECLSPEC_HIDDEN; extern void init_locale(void) DECLSPEC_HIDDEN; +extern HANDLE get_console_wait_handle( HANDLE handle ) DECLSPEC_HIDDEN; extern const WCHAR windows_dir[] DECLSPEC_HIDDEN; extern const WCHAR system_dir[] DECLSPEC_HIDDEN; diff --git a/dlls/kernelbase/sync.c b/dlls/kernelbase/sync.c index 7ea70202c2..13a9938e7c 100644 --- a/dlls/kernelbase/sync.c +++ b/dlls/kernelbase/sync.c @@ -213,8 +213,6 @@ ULONGLONG WINAPI DECLSPEC_HOTPATCH GetTickCount64(void) static HANDLE normalize_handle_if_console( HANDLE handle ) { - static HANDLE wait_event; - if ((handle == (HANDLE)STD_INPUT_HANDLE) || (handle == (HANDLE)STD_OUTPUT_HANDLE) || (handle == (HANDLE)STD_ERROR_HANDLE)) @@ -223,23 +221,7 @@ static HANDLE normalize_handle_if_console( HANDLE handle ) /* even screen buffer console handles are waitable, and are * handled as a handle to the console itself */ - if (is_console_handle( handle )) - { - HANDLE event = 0; - - SERVER_START_REQ( get_console_wait_event ) - { - req->handle = wine_server_obj_handle( console_handle_map( handle )); - if (!wine_server_call( req )) event = wine_server_ptr_handle( reply->event ); - } - SERVER_END_REQ; - if (event) - { - if (InterlockedCompareExchangePointer( &wait_event, event, 0 )) NtClose( event ); - handle = wait_event; - } - } - return handle; + return is_console_handle( handle ) ? get_console_wait_handle( handle ) : handle; }