In case some application decides to call FreeConsole, the opened msvcrt console handles will still prevent conhost.exe from exiting.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/msvcrt/console.c | 88 +++++++++++++++++++++++++++---------------- dlls/msvcrt/main.c | 1 - dlls/msvcrt/msvcrt.h | 1 - 3 files changed, 55 insertions(+), 35 deletions(-)
diff --git a/dlls/msvcrt/console.c b/dlls/msvcrt/console.c index 26f7b554636..67782cc23b8 100644 --- a/dlls/msvcrt/console.c +++ b/dlls/msvcrt/console.c @@ -33,25 +33,43 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt); #define LOCK_CONSOLE _lock(_CONIO_LOCK) #define UNLOCK_CONSOLE _unlock(_CONIO_LOCK)
-static HANDLE MSVCRT_console_in = INVALID_HANDLE_VALUE; -static HANDLE MSVCRT_console_out= INVALID_HANDLE_VALUE; +static HANDLE MSVCRT_console_in; +static HANDLE MSVCRT_console_out; static int __MSVCRT_console_buffer = EOF; static wchar_t __MSVCRT_console_buffer_w = WEOF;
/* INTERNAL: Initialise console handles */ -void msvcrt_init_console(void) +static HANDLE msvcrt_input_console(void) { - TRACE(":Opening console handles\n"); - - MSVCRT_console_in = CreateFileA("CONIN$", GENERIC_WRITE|GENERIC_READ, - FILE_SHARE_WRITE|FILE_SHARE_READ, - NULL, OPEN_EXISTING, 0, NULL); - MSVCRT_console_out= CreateFileA("CONOUT$", GENERIC_WRITE, FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, 0, NULL); + HANDLE console; + LOCK_CONSOLE; + if (!MSVCRT_console_in) + { + MSVCRT_console_in = CreateFileA("CONIN$", GENERIC_WRITE|GENERIC_READ, + FILE_SHARE_WRITE|FILE_SHARE_READ, + NULL, OPEN_EXISTING, 0, NULL); + if (MSVCRT_console_in == INVALID_HANDLE_VALUE) + WARN("Input console handle initialization failed!\n"); + } + console = MSVCRT_console_in; + UNLOCK_CONSOLE; + return console; +}
- if ((MSVCRT_console_in == INVALID_HANDLE_VALUE) || - (MSVCRT_console_out== INVALID_HANDLE_VALUE)) - WARN(":Console handle Initialisation FAILED!\n"); +static HANDLE msvcrt_output_console(void) +{ + HANDLE console; + LOCK_CONSOLE; + if (!MSVCRT_console_out) + { + MSVCRT_console_out = CreateFileA("CONOUT$", GENERIC_WRITE, FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, 0, NULL); + if (MSVCRT_console_out == INVALID_HANDLE_VALUE) + WARN("Output console handle initialization failed!\n"); + } + console = MSVCRT_console_out; + UNLOCK_CONSOLE; + return console; }
/* INTERNAL: Free console handles */ @@ -74,7 +92,7 @@ int CDECL _cputs(const char* str) len = strlen(str);
LOCK_CONSOLE; - if (WriteConsoleA(MSVCRT_console_out, str, len, &count, NULL) + if (WriteConsoleA(msvcrt_output_console(), str, len, &count, NULL) && count == len) retval = 0; UNLOCK_CONSOLE; @@ -93,7 +111,7 @@ int CDECL _cputws(const wchar_t* str) len = wcslen(str);
LOCK_CONSOLE; - if (WriteConsoleW(MSVCRT_console_out, str, len, &count, NULL) + if (WriteConsoleW(msvcrt_output_console(), str, len, &count, NULL) && count == len) retval = 0; UNLOCK_CONSOLE; @@ -162,16 +180,17 @@ int CDECL _getch_nolock(void) } else { + HANDLE console = msvcrt_input_console(); INPUT_RECORD ir; DWORD count; DWORD mode = 0;
- GetConsoleMode(MSVCRT_console_in, &mode); + GetConsoleMode(console, &mode); if(mode) - SetConsoleMode(MSVCRT_console_in, 0); + SetConsoleMode(console, 0);
do { - if (ReadConsoleInputA(MSVCRT_console_in, &ir, 1, &count)) + if (ReadConsoleInputA(console, &ir, 1, &count)) { /* Only interested in ASCII chars */ if (ir.EventType == KEY_EVENT && @@ -197,7 +216,7 @@ int CDECL _getch_nolock(void) break; } while(1); if (mode) - SetConsoleMode(MSVCRT_console_in, mode); + SetConsoleMode(console, mode); } return retval; } @@ -229,16 +248,17 @@ wchar_t CDECL _getwch_nolock(void) } else { + HANDLE console = msvcrt_input_console(); INPUT_RECORD ir; DWORD count; DWORD mode = 0;
- GetConsoleMode(MSVCRT_console_in, &mode); + GetConsoleMode(console, &mode); if(mode) - SetConsoleMode(MSVCRT_console_in, 0); + SetConsoleMode(console, 0);
do { - if (ReadConsoleInputW(MSVCRT_console_in, &ir, 1, &count)) + if (ReadConsoleInputW(console, &ir, 1, &count)) { /* Only interested in ASCII chars */ if (ir.EventType == KEY_EVENT && @@ -264,7 +284,7 @@ wchar_t CDECL _getwch_nolock(void) break; } while(1); if (mode) - SetConsoleMode(MSVCRT_console_in, mode); + SetConsoleMode(console, mode); } return retval; } @@ -288,7 +308,7 @@ wchar_t CDECL _getwch(void) int CDECL _putch_nolock(int c) { DWORD count; - if (WriteConsoleA(MSVCRT_console_out, &c, 1, &count, NULL) && count == 1) + if (WriteConsoleA(msvcrt_output_console(), &c, 1, &count, NULL) && count == 1) return c; return EOF; } @@ -310,7 +330,7 @@ int CDECL _putch(int c) wchar_t CDECL _putwch_nolock(wchar_t c) { DWORD count; - if (WriteConsoleW(MSVCRT_console_out, &c, 1, &count, NULL) && count==1) + if (WriteConsoleW(msvcrt_output_console(), &c, 1, &count, NULL) && count==1) return c; return WEOF; } @@ -381,6 +401,7 @@ wchar_t CDECL _getwche(void) */ char* CDECL _cgets(char* str) { + HANDLE console = msvcrt_input_console(); char *buf = str + 2; DWORD got; DWORD conmode = 0; @@ -388,10 +409,10 @@ char* CDECL _cgets(char* str) TRACE("(%p)\n", str); str[1] = 0; /* Length */ LOCK_CONSOLE; - GetConsoleMode(MSVCRT_console_in, &conmode); - SetConsoleMode(MSVCRT_console_in, ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_INPUT); + GetConsoleMode(console, &conmode); + SetConsoleMode(console, ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT|ENABLE_PROCESSED_INPUT);
- if(ReadConsoleA(MSVCRT_console_in, buf, str[0], &got, NULL)) { + if(ReadConsoleA(console, buf, str[0], &got, NULL)) { if(buf[got-2] == '\r') { buf[got-2] = 0; str[1] = got-2; @@ -409,7 +430,7 @@ char* CDECL _cgets(char* str) } else buf = NULL; - SetConsoleMode(MSVCRT_console_in, conmode); + SetConsoleMode(console, conmode); UNLOCK_CONSOLE; return buf; } @@ -472,12 +493,13 @@ int CDECL _kbhit(void) { /* FIXME: There has to be a faster way than this in Win32.. */ INPUT_RECORD *ir = NULL; + HANDLE console = msvcrt_input_console(); DWORD count = 0, i;
- GetNumberOfConsoleInputEvents(MSVCRT_console_in, &count); + GetNumberOfConsoleInputEvents(console, &count);
if (count && (ir = malloc(count * sizeof(INPUT_RECORD))) && - PeekConsoleInputA(MSVCRT_console_in, ir, count, &count)) + PeekConsoleInputA(console, ir, count, &count)) for(i = 0; i < count - 1; i++) { if (ir[i].EventType == KEY_EVENT && @@ -497,7 +519,7 @@ int CDECL _kbhit(void) static int puts_clbk_console_a(void *ctx, int len, const char *str) { LOCK_CONSOLE; - if(!WriteConsoleA(MSVCRT_console_out, str, len, NULL, NULL)) + if(!WriteConsoleA(msvcrt_output_console(), str, len, NULL, NULL)) len = -1; UNLOCK_CONSOLE; return len; @@ -506,7 +528,7 @@ static int puts_clbk_console_a(void *ctx, int len, const char *str) static int puts_clbk_console_w(void *ctx, int len, const wchar_t *str) { LOCK_CONSOLE; - if(!WriteConsoleW(MSVCRT_console_out, str, len, NULL, NULL)) + if(!WriteConsoleW(msvcrt_output_console(), str, len, NULL, NULL)) len = -1; UNLOCK_CONSOLE; return len; diff --git a/dlls/msvcrt/main.c b/dlls/msvcrt/main.c index 0da4885c7a5..61e8479bf90 100644 --- a/dlls/msvcrt/main.c +++ b/dlls/msvcrt/main.c @@ -113,7 +113,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) } msvcrt_init_math(hinstDLL); msvcrt_init_io(); - msvcrt_init_console(); msvcrt_init_args(); msvcrt_init_signals(); #if _MSVCR_VER >= 100 && _MSVCR_VER <= 120 diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h index 0a742807430..8f6ee08ef2a 100644 --- a/dlls/msvcrt/msvcrt.h +++ b/dlls/msvcrt/msvcrt.h @@ -232,7 +232,6 @@ extern BOOL msvcrt_init_locale(void) DECLSPEC_HIDDEN; extern void msvcrt_init_math(void*) DECLSPEC_HIDDEN; extern void msvcrt_init_io(void) DECLSPEC_HIDDEN; extern void msvcrt_free_io(void) DECLSPEC_HIDDEN; -extern void msvcrt_init_console(void) DECLSPEC_HIDDEN; extern void msvcrt_free_console(void) DECLSPEC_HIDDEN; extern void msvcrt_init_args(void) DECLSPEC_HIDDEN; extern void msvcrt_free_args(void) DECLSPEC_HIDDEN;
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/kernelbase/console.c | 1 - 1 file changed, 1 deletion(-)
diff --git a/dlls/kernelbase/console.c b/dlls/kernelbase/console.c index 8d440c89296..6a3bfdeba65 100644 --- a/dlls/kernelbase/console.c +++ b/dlls/kernelbase/console.c @@ -1844,7 +1844,6 @@ void init_console( void ) if (params->ConsoleHandle && create_console_connection( params->ConsoleHandle )) { init_console_std_handles( FALSE ); - console_flags = 0; } } else if (params->ConsoleHandle == CONSOLE_HANDLE_ALLOC)
Signed-off-by: Jacek Caban jacek@codeweavers.com
Hi Rémi,
On 3/12/21 11:02 AM, Rémi Bernon wrote:
+static HANDLE msvcrt_input_console(void) {
- HANDLE console;
- LOCK_CONSOLE;
- if (!MSVCRT_console_in)
- {
- MSVCRT_console_in = CreateFileA("CONIN$", GENERIC_WRITE|GENERIC_READ,
FILE_SHARE_WRITE|FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, NULL);
- if (MSVCRT_console_in == INVALID_HANDLE_VALUE)
WARN("Input console handle initialization failed!\n");
- }
- console = MSVCRT_console_in;
- UNLOCK_CONSOLE;
- return console;
+}
I think that the caller should be responsible for locking. It's especially important for the _nolock functions that shouldn't lock at all.
Thanks, Piotr
On 3/12/21 1:27 PM, Piotr Caban wrote:
Hi Rémi,
On 3/12/21 11:02 AM, Rémi Bernon wrote:
+static HANDLE msvcrt_input_console(void) {
+ HANDLE console; + LOCK_CONSOLE; + if (!MSVCRT_console_in) + { + MSVCRT_console_in = CreateFileA("CONIN$", GENERIC_WRITE|GENERIC_READ, + FILE_SHARE_WRITE|FILE_SHARE_READ, + NULL, OPEN_EXISTING, 0, NULL); + if (MSVCRT_console_in == INVALID_HANDLE_VALUE) + WARN("Input console handle initialization failed!\n"); + } + console = MSVCRT_console_in; + UNLOCK_CONSOLE; + return console; +}
I think that the caller should be responsible for locking. It's especially important for the _nolock functions that shouldn't lock at all.
Thanks, Piotr
Ah alright, so how should these be handled? We could also probably make the helper lockfree with interlocked exchange.
On 3/12/21 1:31 PM, Rémi Bernon wrote:
On 3/12/21 1:27 PM, Piotr Caban wrote:
Hi Rémi,
On 3/12/21 11:02 AM, Rémi Bernon wrote:
+static HANDLE msvcrt_input_console(void) {
+ HANDLE console; + LOCK_CONSOLE; + if (!MSVCRT_console_in) + { + MSVCRT_console_in = CreateFileA("CONIN$", GENERIC_WRITE|GENERIC_READ, + FILE_SHARE_WRITE|FILE_SHARE_READ, + NULL, OPEN_EXISTING, 0, NULL); + if (MSVCRT_console_in == INVALID_HANDLE_VALUE) + WARN("Input console handle initialization failed!\n"); + } + console = MSVCRT_console_in; + UNLOCK_CONSOLE; + return console; +}
I think that the caller should be responsible for locking. It's especially important for the _nolock functions that shouldn't lock at all.
Thanks, Piotr
Ah alright, so how should these be handled? We could also probably make the helper lockfree with interlocked exchange.
You can just remove the LOCK_CONSOLE/UNLOCK_CONSOLE from the msvcrt_input_console/msvcrt_output_console functions (it also makes the console handle not needed). In case of _nolock function the application is responsible for making sure the functions are called in thread-safe contexts.