From 887c9d97e3841dac92fd720607b77c4b48c73d6b Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 28 Oct 2014 15:35:10 +0000 Subject: [PATCH] Print error message strings on Windows Signed-off-by: David Woodhouse --- compat.c | 29 +++++++++++++++++++++++++ configure.ac | 3 +++ java/src/com/example/LibTest.java | 2 +- libopenconnect.map.in | 2 +- main.c | 20 ++++++++++++------ mainloop.c | 6 ++++-- openconnect-internal.h | 1 + script.c | 6 ++++-- tun-win32.c | 35 ++++++++++++++++++++----------- 9 files changed, 80 insertions(+), 24 deletions(-) diff --git a/compat.c b/compat.c index 44528641..43ac9252 100644 --- a/compat.c +++ b/compat.c @@ -228,6 +228,35 @@ int openconnect__inet_aton(const char *cp, struct in_addr *addr) #endif #ifdef _WIN32 +char *openconnect__win32_strerror(DWORD err) +{ + wchar_t *msgw; + char *msgutf8; + int nr_chars; + + if (!FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, err, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPWSTR)&msgw, 0, NULL)) { + if (asprintf(&msgutf8, _("(error 0x%x)"), err) != -1) + return msgutf8; + fail: + return strdup(_("(Error while describing error!)")); + } + + nr_chars = WideCharToMultiByte(CP_UTF8, 0, msgw, -1, NULL, 0, NULL, NULL); + + msgutf8 = malloc(nr_chars); + if (!msgutf8) + goto fail; + + WideCharToMultiByte(CP_UTF8, 0, msgw, -1, msgutf8, nr_chars, NULL, NULL); + LocalFree(msgw); + return msgutf8; +} + void openconnect__win32_sock_init() { WSADATA data; diff --git a/configure.ac b/configure.ac index ef335628..1cf1cf6c 100644 --- a/configure.ac +++ b/configure.ac @@ -25,6 +25,7 @@ symver_time= symver_getline= symver_asprintf= symver_vasprintf= +symver_win32_strerror= case $host_os in *linux* | *gnu*) @@ -54,6 +55,7 @@ case $host_os in have_win=yes # For asprintf() AC_DEFINE(_GNU_SOURCE, 1, [_GNU_SOURCE]) + symver_win32_strerror="openconnect__win32_strerror;" ;; *) # On FreeBSD the only way to get vsyslog() visible is to define @@ -139,6 +141,7 @@ AC_SUBST(SYMVER_TIME, $symver_time) AC_SUBST(SYMVER_GETLINE, $symver_getline) AC_SUBST(SYMVER_ASPRINTF, $symver_asprintf) AC_SUBST(SYMVER_VASPRINTF, $symver_vasprintf) +AC_SUBST(SYMVER_WIN32_STRERROR, $symver_win32_strerror) AS_COMPILER_FLAGS(WFLAGS, "-Wall diff --git a/java/src/com/example/LibTest.java b/java/src/com/example/LibTest.java index 48066bae..b515e4b7 100644 --- a/java/src/com/example/LibTest.java +++ b/java/src/com/example/LibTest.java @@ -209,7 +209,7 @@ public static void main(String argv[]) { lib.setCSDWrapper("csd.sh", null, null); } lib.parseURL(argv[0]); - + lib.setSystemTrust(true); int ret = lib.obtainCookie(); if (ret < 0) die("obtainCookie() returned error"); diff --git a/libopenconnect.map.in b/libopenconnect.map.in index e7b833b0..87e6f9e4 100644 --- a/libopenconnect.map.in +++ b/libopenconnect.map.in @@ -65,7 +65,7 @@ OPENCONNECT_4.1 { OPENCONNECT_PRIVATE { - global: @SYMVER_TIME@ @SYMVER_GETLINE@ @SYMVER_JAVA@ @SYMVER_ASPRINTF@ @SYMVER_VASPRINTF@ + global: @SYMVER_TIME@ @SYMVER_GETLINE@ @SYMVER_JAVA@ @SYMVER_ASPRINTF@ @SYMVER_VASPRINTF@ @SYMVER_WIN32_STRERROR@ openconnect_version_str; openconnect_sha1; openconnect_open_utf8; diff --git a/main.c b/main.c index b4087677..13c46ff7 100644 --- a/main.c +++ b/main.c @@ -299,8 +299,10 @@ static char *convert_arg_to_utf8(char **argv, char *arg) argv_w = CommandLineToArgvW(GetCommandLineW(), &argc_w); if (!argv_w) { - fprintf(stderr, _("CommandLineToArgvW() failed: %lx\n"), - GetLastError()); + char *errstr = openconnect__win32_strerror(GetLastError()); + fprintf(stderr, _("CommandLineToArgvW() failed: %s\n"), + errstr); + free(errstr); exit(1); } } @@ -346,7 +348,9 @@ static void read_stdin(char **string, int hidden) } if (!ReadConsoleW(stdinh, wbuf, sizeof(wbuf)/2, &nr_read, &rcc)) { - fprintf(stderr, _("ReadConsole() error %lx\n"), GetLastError()); + char *errstr = openconnect__win32_strerror(GetLastError()); + fprintf(stderr, _("ReadConsole() failed: %s\n"), errstr); + free(errstr); goto out; } @@ -357,8 +361,10 @@ static void read_stdin(char **string, int hidden) nr_read = WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, NULL, 0, NULL, NULL); if (!nr_read) { + char *errstr = openconnect__win32_strerror(GetLastError()); fprintf(stderr, _("Error converting console input: %lx\n"), - GetLastError()); + errstr); + free(errstr); goto out; } buf = malloc(nr_read); @@ -368,9 +374,11 @@ static void read_stdin(char **string, int hidden) } if (!WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, buf, nr_read, NULL, NULL)) { + char *errstr = openconnect__win32_strerror(GetLastError()); + fprintf(stderr, _("Error converting console input: %s\n"), + errstr); + free(errstr); free(buf); - fprintf(stderr, _("Error converting console input: %lx\n"), - GetLastError()); goto out; } diff --git a/mainloop.c b/mainloop.c index 6e7501e5..5947917a 100644 --- a/mainloop.c +++ b/mainloop.c @@ -206,9 +206,11 @@ int openconnect_mainloop(struct openconnect_info *vpninfo, events[nr_events++] = vpninfo->tun_rd_overlap.hEvent; } if (WaitForMultipleObjects(nr_events, events, FALSE, timeout) == WAIT_FAILED) { + char *errstr = openconnect__win32_strerror(GetLastError()); vpn_progress(vpninfo, PRG_ERR, - _("WaitForMultipleObjects failed: %lx\n"), - GetLastError()); + _("WaitForMultipleObjects failed: %s\n"), + errstr); + free(errstr); } #else memcpy(&rfds, &vpninfo->_select_rfds, sizeof(rfds)); diff --git a/openconnect-internal.h b/openconnect-internal.h index 313a43e6..91db620c 100644 --- a/openconnect-internal.h +++ b/openconnect-internal.h @@ -527,6 +527,7 @@ static inline int set_fd_cloexec(int fd) #ifdef _WIN32 #define pipe(fds) _pipe(fds, 4096, O_BINARY) void openconnect__win32_sock_init(); +char *openconnect__win32_strerror(DWORD err); #undef inet_pton #define inet_pton openconnect__win32_inet_pton int openconnect__win32_inet_pton(int af, const char *src, void *dst); diff --git a/script.c b/script.c index d0eddd39..b1566dee 100644 --- a/script.c +++ b/script.c @@ -363,9 +363,11 @@ int script_config_tun(struct openconnect_info *vpninfo, const char *reason) } if (ret < 0) { + char *errstr = openconnect__win32_strerror(GetLastError()); vpn_progress(vpninfo, PRG_ERR, - _("Failed to spawn script '%s' for %s: %d\n"), - vpninfo->vpnc_script, reason, (int)GetLastError()); + _("Failed to spawn script '%s' for %s: %s\n"), + vpninfo->vpnc_script, reason, errstr); + free(errstr); goto cleanup; } diff --git a/tun-win32.c b/tun-win32.c index cc054989..b6a0b903 100644 --- a/tun-win32.c +++ b/tun-win32.c @@ -178,10 +178,11 @@ static intptr_t open_tun(struct openconnect_info *vpninfo, char *guid, char *nam if (!DeviceIoControl(tun_fh, TAP_IOCTL_GET_VERSION, data, sizeof(&data), data, sizeof(data), &len, NULL)) { - DWORD err = GetLastError(); + char *errstr = openconnect__win32_strerror(GetLastError()); vpn_progress(vpninfo, PRG_ERR, - _("Failed to obtain TAP driver version: %lx\n"), err); + _("Failed to obtain TAP driver version: %s\n"), errstr); + free(errstr); return -1; } if (data[0] < 9 || (data[0] == 9 && data[1] < 9)) { @@ -200,10 +201,11 @@ static intptr_t open_tun(struct openconnect_info *vpninfo, char *guid, char *nam if (!DeviceIoControl(tun_fh, TAP_IOCTL_CONFIG_TUN, data, sizeof(data), data, sizeof(data), &len, NULL)) { - DWORD err = GetLastError(); + char *errstr = openconnect__win32_strerror(GetLastError()); vpn_progress(vpninfo, PRG_ERR, - _("Failed to set TAP IP addresses: %lx\n"), err); + _("Failed to set TAP IP addresses: %s\n"), errstr); + free(errstr); return -1; } @@ -211,10 +213,11 @@ static intptr_t open_tun(struct openconnect_info *vpninfo, char *guid, char *nam if (!DeviceIoControl(tun_fh, TAP_IOCTL_SET_MEDIA_STATUS, data, sizeof(data[0]), data, sizeof(data[0]), &len, NULL)) { - DWORD err = GetLastError(); + char *errstr = openconnect__win32_strerror(GetLastError()); vpn_progress(vpninfo, PRG_ERR, - _("Failed to set TAP media status: %lx\n"), err); + _("Failed to set TAP media status: %s\n"), errstr); + free(errstr); return -1; } if (!vpninfo->ifname) @@ -240,10 +243,13 @@ int os_read_tun(struct openconnect_info *vpninfo, struct pkt *pkt) if (err == ERROR_IO_PENDING) vpninfo->tun_rd_pending = 1; - else + else { + char *errstr = openconnect__win32_strerror(err); vpn_progress(vpninfo, PRG_ERR, - _("Failed to read from TAP device: %lx\n"), - err); + _("Failed to read from TAP device: %s\n"), + errstr); + free(errstr); + } return -1; } else if (!GetOverlappedResult(vpninfo->tun_fh, &vpninfo->tun_rd_overlap, &pkt_size, @@ -251,10 +257,12 @@ int os_read_tun(struct openconnect_info *vpninfo, struct pkt *pkt) DWORD err = GetLastError(); if (err != ERROR_IO_INCOMPLETE) { + char *errstr = openconnect__win32_strerror(err); vpninfo->tun_rd_pending = 0; vpn_progress(vpninfo, PRG_ERR, - _("Failed to complete read from TAP device: %lx\n"), - err); + _("Failed to complete read from TAP device: %s\n"), + errstr); + free(errstr); goto reread; } return -1; @@ -271,6 +279,7 @@ int os_write_tun(struct openconnect_info *vpninfo, struct pkt *pkt) { DWORD pkt_size = 0; DWORD err; + char *errstr; if (WriteFile(vpninfo->tun_fh, pkt->data, pkt->len, &pkt_size, &vpninfo->tun_wr_overlap)) { vpn_progress(vpninfo, PRG_TRACE, @@ -292,8 +301,10 @@ int os_write_tun(struct openconnect_info *vpninfo, struct pkt *pkt) } err = GetLastError(); } + errstr = openconnect__win32_strerror(err); vpn_progress(vpninfo, PRG_ERR, - _("Failed to write to TAP device: %lx\n"), err); + _("Failed to write to TAP device: %s\n"), errstr); + free(errstr); return -1; }