From 2e3c6330c4079d113b4faeb0399aa8b19622710d Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Wed, 31 Mar 2021 14:35:33 +0100 Subject: [PATCH] Fix output redirection under Windows If WriteConsoleW() fails, convert to the *console* code page and write to stdout/stderr (as appropriate) with fwrite(). Mostly researched by bers in !177. Fixes: #229 Signed-off-by: David Woodhouse --- main.c | 31 +++++++++++++++++++++++++------ www/changelog.xml | 1 + 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/main.c b/main.c index c940a03f..ba5af16e 100644 --- a/main.c +++ b/main.c @@ -317,14 +317,33 @@ static int __attribute__ ((format(printf, 2, 0))) HANDLE h = GetStdHandle(f == stdout ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE); wchar_t wbuf[1024]; char buf[1024]; - int chars, wchars; + int bytes, wchars; - buf[sizeof(buf) - 1] = 0; - chars = _vsnprintf(buf, sizeof(buf) - 1, fmt, args); - wchars = MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, sizeof(wbuf)/2); - WriteConsoleW(h, wbuf, wchars, NULL, NULL); + /* No need to NUL-terminate strings here */ + bytes = _vsnprintf(buf, sizeof(buf), fmt, args); + if (bytes < 0) + return bytes; + if (bytes > sizeof(buf)) + bytes = sizeof(buf); - return chars; + wchars = MultiByteToWideChar(CP_UTF8, 0, buf, bytes, wbuf, sizeof(wbuf)/2); + if (!wchars) + return -1; + + /* + * If writing to console fails, that's probably due to redirection. + * Convert to console CP and write to the FH, following the example of + * https://github.com/wine-mirror/wine/blob/e909986e6e/programs/whoami/main.c#L33-L49 + */ + if (!WriteConsoleW(h, wbuf, wchars, NULL, NULL)) { + bytes = WideCharToMultiByte(GetConsoleOutputCP(), 0, wbuf, wchars, + buf, sizeof(buf), NULL, NULL); + if (!bytes) + return -1; + + return fwrite(buf, 1, bytes, f); + } + return bytes; } static int __attribute__ ((format(printf, 2, 3))) diff --git a/www/changelog.xml b/www/changelog.xml index 23085a53..3027ee71 100644 --- a/www/changelog.xml +++ b/www/changelog.xml @@ -36,6 +36,7 @@
  • Add support for PPP-based protocols, currently over TLS only (!165).
  • Add support for two PPP-based protocols, F5 with --protocol=f5 and Fortinet with --protocol=fortinet (!169).
  • Add support for Wintun Layer 3 TUN driver under Windows.
  • +
  • Fix output redirection under Windows (#229)

  • OpenConnect v8.10 -- 2.50.1