From 8c41b8aac3efb78178fe1eaf52d8d1bbc44941a8 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Fri, 5 Mar 2021 15:33:40 +0100 Subject: [PATCH] w32: Always use Unicode for console input and output. * common/init.c (_init_common_subsystems) [W32]: Set the codepage to UTF-8 for input and putput. Switch gettext to UTF-8. * tools/gpgconf.c (main): Display the input and output codepage if they differ. * g10/gpg.c (utf8_strings) [W32]: Make sure this is always set. -- With this patch the former patch to use ReadConsoleW and WriteConsoleW in ttyio.c are kind of superfluous because the ANSI version of these functions are also able to read/write UTF-8 directly given the console code page has been set correctly. However, this seems to work only with recent versions of Windows-10. GnuPG-bug-id: 4365 --- common/init.c | 11 +++++++++++ doc/gpg.texi | 19 +++++++++++++------ g10/gpg.c | 14 ++++++++++++-- tools/gpgconf.c | 6 +++++- 4 files changed, 41 insertions(+), 9 deletions(-) diff --git a/common/init.c b/common/init.c index ba20cd8d0..7b6b4aea0 100644 --- a/common/init.c +++ b/common/init.c @@ -202,6 +202,17 @@ _init_common_subsystems (gpg_err_source_t errsource, int *argcp, char ***argvp) parse_std_file_handles (argcp, argvp); #endif +#ifdef HAVE_W32_SYSTEM + /* We want gettext to always output UTF-8 and we put the console in + * utf-8 mode. */ + gettext_use_utf8 (1); + if (!SetConsoleCP (CP_UTF8) || !SetConsoleOutputCP (CP_UTF8)) + { + log_info ("SetConsoleCP failed: %s\n", w32_strerror (-1)); + log_info ("Warning: Garbled console data possible\n"); + } +#endif + /* Access the standard estreams as early as possible. If we don't do this the original stdio streams may have been closed when _es_get_std_stream is first use and in turn it would connect to diff --git a/doc/gpg.texi b/doc/gpg.texi index 6b912d674..b93b52cd7 100644 --- a/doc/gpg.texi +++ b/doc/gpg.texi @@ -1529,13 +1529,14 @@ not used). @item --display-charset @var{name} @opindex display-charset -Set the name of the native character set. This is used to convert -some informational strings like user IDs to the proper UTF-8 encoding. +Set the name of the native character set. This is used to convert some +informational strings like user IDs to the proper UTF-8 encoding. Note that this has nothing to do with the character set of data to be -encrypted or signed; GnuPG does not recode user-supplied data. If -this option is not used, the default character set is determined from -the current locale. A verbosity level of 3 shows the chosen set. -Valid values for @var{name} are: +encrypted or signed; GnuPG does not recode user-supplied data. If this +option is not used, the default character set is determined from the +current locale. A verbosity level of 3 shows the chosen set. This +option should not be used on Windows. Valid values for @var{name} +are: @table @asis @@ -1571,6 +1572,12 @@ encoded in the character set as specified by @option{--display-charset}. These options affect all following arguments. Both options may be used multiple times. +This option has no effect on Windows. There the internal used UTF-8 +encoding is translated for console input and output. The command line +arguments are expected as Unicode and translated to UTF-8. Thus when +calling this program from another, make sure to use the Unicode +version of CreateProcess. + @anchor{gpg-option --options} @item --options @var{file} @opindex options diff --git a/g10/gpg.c b/g10/gpg.c index 8e19a89f3..c61f17188 100644 --- a/g10/gpg.c +++ b/g10/gpg.c @@ -1007,7 +1007,13 @@ static struct debug_flags_s debug_flags [] = int g10_errors_seen = 0; -static int utf8_strings = 0; +static int utf8_strings = +#ifdef HAVE_W32_SYSTEM + 1 +#else + 0 +#endif + ; static int maybe_setuid = 1; static unsigned int opt_set_iobuf_size; static unsigned int opt_set_iobuf_size_used; @@ -3406,7 +3412,11 @@ main (int argc, char **argv) opt.verify_options&=~VERIFY_SHOW_NOTATIONS; break; case oUtf8Strings: utf8_strings = 1; break; - case oNoUtf8Strings: utf8_strings = 0; break; + case oNoUtf8Strings: +#ifdef HAVE_W32_SYSTEM + utf8_strings = 0; +#endif + break; case oDisableCipherAlgo: { int algo = string_to_cipher_algo (pargs.r.ret_str); diff --git a/tools/gpgconf.c b/tools/gpgconf.c index 13170e452..63c305483 100644 --- a/tools/gpgconf.c +++ b/tools/gpgconf.c @@ -945,7 +945,11 @@ main (int argc, char **argv) #ifdef HAVE_W32_SYSTEM { get_outfp (&outfp); - es_fprintf (outfp, "Console: CP%u\n", GetConsoleOutputCP ()); + if (GetConsoleCP () != GetConsoleOutputCP ()) + es_fprintf (outfp, "Console: CP%u/CP%u\n", + GetConsoleCP (), GetConsoleOutputCP ()); + else + es_fprintf (outfp, "Console: CP%u\n", GetConsoleCP ()); es_fprintf (outfp, "ANSI: CP%u\n", GetACP ()); es_fprintf (outfp, "OEM: CP%u\n", GetOEMCP ()); }