summaryrefslogtreecommitdiff
path: root/src/tool_doswin.c
diff options
context:
space:
mode:
authorJay Satiro <raysatiro@yahoo.com>2020-11-19 16:49:24 -0500
committerJay Satiro <raysatiro@yahoo.com>2021-01-12 03:44:48 -0500
commit3831043eff9ed412428150537374facb609e5b33 (patch)
treeac7dc2f8ae313fa7afcb864adf102beb50e4772b /src/tool_doswin.c
parent33993d45fe229b1798a94de85c3642a4b001c4de (diff)
downloadcurl-3831043eff9ed412428150537374facb609e5b33.tar.gz
tool_doswin: Restore original console settings on CTRL signal
- Move Windows terminal init code from tool_main to tool_doswin. - Restore the original console settings on CTRL+C and CTRL+BREAK. Background: On Windows the curl tool changes the console settings to enable virtual terminal processing (eg color output) if supported (ie Win 10). The original settings are restored on exit but prior to this change were not restored in the case of the CTRL signals. Windows VT behavior varies depending on console/powershell/terminal; refer to the discussion in #6226. Assisted-by: Rich Turner Closes https://github.com/curl/curl/pull/6226
Diffstat (limited to 'src/tool_doswin.c')
-rw-r--r--src/tool_doswin.c62
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;
}