diff options
Diffstat (limited to 'src/tool_doswin.c')
-rw-r--r-- | src/tool_doswin.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/src/tool_doswin.c b/src/tool_doswin.c index 2ae6ba788..b70100abe 100644 --- a/src/tool_doswin.c +++ b/src/tool_doswin.c @@ -28,6 +28,7 @@ #endif #ifdef WIN32 +# include <stdlib.h> # include <tlhelp32.h> # include "tool_cfgable.h" # include "tool_libinfo.h" @@ -702,6 +703,64 @@ cleanup: return slist; } +/* The terminal settings to restore on exit */ +static struct TerminalSettings { + HANDLE hStdOut; + DWORD dwOutputMode; + LONG valid; +} TerminalSettings; + +#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING +#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004 +#endif + +static void restore_terminal(void) +{ + if(InterlockedExchange(&TerminalSettings.valid, (LONG)FALSE)) + SetConsoleMode(TerminalSettings.hStdOut, TerminalSettings.dwOutputMode); +} + +/* This is the console signal handler. + * The system calls it in a separate thread. + */ +static BOOL WINAPI signal_handler(DWORD type) +{ + if(type == CTRL_C_EVENT || type == CTRL_BREAK_EVENT) + restore_terminal(); + return FALSE; +} + +static void init_terminal(void) +{ + TerminalSettings.hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); + /* + * Enable VT (Virtual Terminal) output. + * Note: VT mode flag can be set on any version of Windows, but VT + * processing only performed on Win10 >= Creators Update) + */ + if((TerminalSettings.hStdOut != INVALID_HANDLE_VALUE) && + GetConsoleMode(TerminalSettings.hStdOut, + &TerminalSettings.dwOutputMode) && + !(TerminalSettings.dwOutputMode & + ENABLE_VIRTUAL_TERMINAL_PROCESSING)) { + /* The signal handler is set before attempting to change the console mode + because otherwise a signal would not be caught after the change but + before the handler was installed. */ + (void)InterlockedExchange(&TerminalSettings.valid, (LONG)TRUE); + if(SetConsoleCtrlHandler(signal_handler, TRUE)) { + if(SetConsoleMode(TerminalSettings.hStdOut, + (TerminalSettings.dwOutputMode | + ENABLE_VIRTUAL_TERMINAL_PROCESSING))) { + atexit(restore_terminal); + } + else { + SetConsoleCtrlHandler(signal_handler, FALSE); + (void)InterlockedExchange(&TerminalSettings.valid, (LONG)FALSE); + } + } + } +} + LARGE_INTEGER tool_freq; bool tool_isVistaOrGreater; @@ -714,6 +773,9 @@ CURLcode win32_init(void) tool_isVistaOrGreater = false; QueryPerformanceFrequency(&tool_freq); + + init_terminal(); + return CURLE_OK; } |