From: Daniel Stenberg Date: Fri, 9 May 2025 08:21:53 +0000 (+0200) Subject: curlx: add curlx_winapi_ functions X-Git-Tag: curl-8_14_0~122 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c74d3e10d2935a9a37ffe6b2f7a4ecb0f81e974f;p=thirdparty%2Fcurl.git curlx: add curlx_winapi_ functions Split them out from lib/strerror. Used by test code. Closes #17299 --- diff --git a/lib/Makefile.inc b/lib/Makefile.inc index 921caf9ccc..08147ebb42 100644 --- a/lib/Makefile.inc +++ b/lib/Makefile.inc @@ -31,7 +31,8 @@ LIB_CURLX_CFILES = \ curlx/timediff.c \ curlx/timeval.c \ curlx/version_win32.c \ - curlx/warnless.c + curlx/warnless.c \ + curlx/winapi.c LIB_CURLX_HFILES = \ curlx/base64.h \ @@ -43,7 +44,8 @@ LIB_CURLX_HFILES = \ curlx/timediff.h \ curlx/timeval.h \ curlx/version_win32.h \ - curlx/warnless.h + curlx/warnless.h \ + curlx/winapi.h LIB_VAUTH_CFILES = \ vauth/cleartext.c \ diff --git a/lib/curlx/curlx.h b/lib/curlx/curlx.h index 1472f5d083..e8249d7f61 100644 --- a/lib/curlx/curlx.h +++ b/lib/curlx/curlx.h @@ -65,4 +65,7 @@ #include "timeval.h" #include "timediff.h" +#include "winapi.h" +/* for curlx_winapi_strerror */ + #endif /* HEADER_CURL_CURLX_H */ diff --git a/lib/curlx/winapi.c b/lib/curlx/winapi.c new file mode 100644 index 0000000000..e79024c69a --- /dev/null +++ b/lib/curlx/winapi.c @@ -0,0 +1,135 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ +#include "../curl_setup.h" + +/* + * curlx_winapi_strerror: + * Variant of Curl_strerror if the error code is definitely Windows API. + */ +#ifdef _WIN32 +#include "winapi.h" + +#ifdef BUILDING_LIBCURL +#include +#define SNPRINTF curl_msnprintf +#else +/* when built for the test servers */ + +/* adjust for old MSVC */ +#if defined(_MSC_VER) && (_MSC_VER < 1900) +# define SNPRINTF _snprintf +#else +#define SNPRINTF snprintf +#endif + +#endif /* !BUILDING_LIBCURL */ + +#ifdef _WIN32 +/* This is a helper function for Curl_strerror that converts Windows API error + * codes (GetLastError) to error messages. + * Returns NULL if no error message was found for error code. + */ +const char *curlx_get_winapi_error(int err, char *buf, size_t buflen) +{ + char *p; + wchar_t wbuf[256]; + + if(!buflen) + return NULL; + + *buf = '\0'; + *wbuf = L'\0'; + + /* We return the local codepage version of the error string because if it is + output to the user's terminal it will likely be with functions which + expect the local codepage (eg fprintf, failf, infof). + FormatMessageW -> wcstombs is used for Windows CE compatibility. */ + if(FormatMessageW((FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS), NULL, (DWORD)err, + LANG_NEUTRAL, wbuf, CURL_ARRAYSIZE(wbuf), NULL)) { + size_t written = wcstombs(buf, wbuf, buflen - 1); + if(written != (size_t)-1) + buf[written] = '\0'; + else + *buf = '\0'; + } + + /* Truncate multiple lines */ + p = strchr(buf, '\n'); + if(p) { + if(p > buf && *(p-1) == '\r') + *(p-1) = '\0'; + else + *p = '\0'; + } + + return *buf ? buf : NULL; +} +#endif /* _WIN32 */ + +const char *curlx_winapi_strerror(DWORD err, char *buf, size_t buflen) +{ +#ifdef PRESERVE_WINDOWS_ERROR_CODE + DWORD old_win_err = GetLastError(); +#endif + int old_errno = errno; + + if(!buflen) + return NULL; + + *buf = '\0'; + +#ifndef CURL_DISABLE_VERBOSE_STRINGS + if(!curlx_get_winapi_error((int)err, buf, buflen)) { +#if defined(__GNUC__) && __GNUC__ >= 7 +#pragma GCC diagnostic push +#pragma GCC diagnostic warning "-Wformat-truncation=1" +#endif + /* some GCC compilers cause false positive warnings if we allow this + warning */ + SNPRINTF(buf, buflen, "Unknown error %lu (0x%08lX)", err, err); +#if defined(__GNUC__) && __GNUC__ >= 7 +#pragma GCC diagnostic pop +#endif + + } +#else + { + const char *txt = (err == ERROR_SUCCESS) ? "No error" : "Error"; + if(strlen(txt) < buflen) + strcpy(buf, txt); + } +#endif + + if(errno != old_errno) + CURL_SETERRNO(old_errno); + +#ifdef PRESERVE_WINDOWS_ERROR_CODE + if(old_win_err != GetLastError()) + SetLastError(old_win_err); +#endif + + return buf; +} +#endif /* _WIN32 */ diff --git a/lib/curlx/winapi.h b/lib/curlx/winapi.h new file mode 100644 index 0000000000..76ddcc53b8 --- /dev/null +++ b/lib/curlx/winapi.h @@ -0,0 +1,33 @@ +#ifndef HEADER_CURLX_WINAPI_H +#define HEADER_CURLX_WINAPI_H +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) Daniel Stenberg, , et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + * SPDX-License-Identifier: curl + * + ***************************************************************************/ + +#ifdef _WIN32 +#define WINAPI_ERROR_LEN 100 +const char *curlx_get_winapi_error(int err, char *buf, size_t buflen); +const char *curlx_winapi_strerror(DWORD err, char *buf, size_t buflen); +#endif + +#endif /* HEADER_CURLX_WINAPI_H */ diff --git a/lib/strerror.c b/lib/strerror.c index 922bb9c5c9..0c440136d0 100644 --- a/lib/strerror.c +++ b/lib/strerror.c @@ -42,6 +42,7 @@ #include "curl_sspi.h" #endif +#include "curlx/winapi.h" #include "strerror.h" /* The last 3 #include files should be in this order */ #include "curl_printf.h" @@ -782,50 +783,6 @@ get_winsock_error(int err, char *buf, size_t len) } #endif /* USE_WINSOCK */ -#ifdef _WIN32 -/* This is a helper function for Curl_strerror that converts Windows API error - * codes (GetLastError) to error messages. - * Returns NULL if no error message was found for error code. - */ -static const char * -get_winapi_error(int err, char *buf, size_t buflen) -{ - char *p; - wchar_t wbuf[256]; - - if(!buflen) - return NULL; - - *buf = '\0'; - *wbuf = L'\0'; - - /* We return the local codepage version of the error string because if it is - output to the user's terminal it will likely be with functions which - expect the local codepage (eg fprintf, failf, infof). - FormatMessageW -> wcstombs is used for Windows CE compatibility. */ - if(FormatMessageW((FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS), NULL, (DWORD)err, - LANG_NEUTRAL, wbuf, CURL_ARRAYSIZE(wbuf), NULL)) { - size_t written = wcstombs(buf, wbuf, buflen - 1); - if(written != (size_t)-1) - buf[written] = '\0'; - else - *buf = '\0'; - } - - /* Truncate multiple lines */ - p = strchr(buf, '\n'); - if(p) { - if(p > buf && *(p-1) == '\r') - *(p-1) = '\0'; - else - *p = '\0'; - } - - return *buf ? buf : NULL; -} -#endif /* _WIN32 */ - /* * Our thread-safe and smart strerror() replacement. * @@ -872,9 +829,9 @@ const char *Curl_strerror(int err, char *buf, size_t buflen) { if( #ifdef USE_WINSOCK - !get_winsock_error(err, buf, buflen) && + !get_winsock_error(err, buf, buflen) && #endif - !get_winapi_error(err, buf, buflen)) + !curlx_get_winapi_error(err, buf, buflen)) curl_msnprintf(buf, buflen, "Unknown error %d (%#x)", err, err); } #else /* not Windows coming up */ @@ -935,47 +892,6 @@ const char *Curl_strerror(int err, char *buf, size_t buflen) return buf; } -/* - * curlx_winapi_strerror: - * Variant of Curl_strerror if the error code is definitely Windows API. - */ -#ifdef _WIN32 -const char *curlx_winapi_strerror(DWORD err, char *buf, size_t buflen) -{ -#ifdef PRESERVE_WINDOWS_ERROR_CODE - DWORD old_win_err = GetLastError(); -#endif - int old_errno = errno; - - if(!buflen) - return NULL; - - *buf = '\0'; - -#ifndef CURL_DISABLE_VERBOSE_STRINGS - if(!get_winapi_error((int)err, buf, buflen)) { - curl_msnprintf(buf, buflen, "Unknown error %lu (0x%08lX)", err, err); - } -#else - { - const char *txt = (err == ERROR_SUCCESS) ? "No error" : "Error"; - if(strlen(txt) < buflen) - strcpy(buf, txt); - } -#endif - - if(errno != old_errno) - CURL_SETERRNO(old_errno); - -#ifdef PRESERVE_WINDOWS_ERROR_CODE - if(old_win_err != GetLastError()) - SetLastError(old_win_err); -#endif - - return buf; -} -#endif /* _WIN32 */ - #ifdef USE_WINDOWS_SSPI /* * Curl_sspi_strerror: @@ -1098,7 +1014,7 @@ const char *Curl_sspi_strerror(int err, char *buf, size_t buflen) } else { char msgbuf[256]; - if(get_winapi_error(err, msgbuf, sizeof(msgbuf))) + if(curlx_get_winapi_error(err, msgbuf, sizeof(msgbuf))) curl_msnprintf(buf, buflen, "%s (0x%08X) - %s", txt, err, msgbuf); else curl_msnprintf(buf, buflen, "%s (0x%08X)", txt, err); diff --git a/lib/strerror.h b/lib/strerror.h index 3dd382b96a..424fb5b7b5 100644 --- a/lib/strerror.h +++ b/lib/strerror.h @@ -29,9 +29,6 @@ #define STRERROR_LEN 256 /* a suitable length */ const char *Curl_strerror(int err, char *buf, size_t buflen); -#ifdef _WIN32 -const char *curlx_winapi_strerror(DWORD err, char *buf, size_t buflen); -#endif #ifdef USE_WINDOWS_SSPI const char *Curl_sspi_strerror(int err, char *buf, size_t buflen); #endif diff --git a/lib/vtls/schannel_verify.c b/lib/vtls/schannel_verify.c index 01d5fb5fea..4834fc450f 100644 --- a/lib/vtls/schannel_verify.c +++ b/lib/vtls/schannel_verify.c @@ -44,6 +44,7 @@ #include "vtls_int.h" #include "../sendf.h" #include "../strerror.h" +#include "../curlx/winapi.h" #include "../curlx/multibyte.h" #include "../curl_printf.h" #include "hostcheck.h" @@ -174,7 +175,7 @@ static CURLcode add_certs_data_to_store(HCERTSTORE trust_store, NULL, NULL, (const void **)&cert_context)) { - char buffer[STRERROR_LEN]; + char buffer[WINAPI_ERROR_LEN]; failf(data, "schannel: failed to extract certificate from CA file " "'%s': %s", @@ -203,7 +204,7 @@ static CURLcode add_certs_data_to_store(HCERTSTORE trust_store, NULL); CertFreeCertificateContext(cert_context); if(!add_cert_result) { - char buffer[STRERROR_LEN]; + char buffer[WINAPI_ERROR_LEN]; failf(data, "schannel: failed to add certificate from CA file '%s' " "to certificate store: %s", @@ -251,7 +252,7 @@ static CURLcode add_certs_file_to_store(HCERTSTORE trust_store, ca_file_tstr = curlx_convert_UTF8_to_tchar(ca_file); if(!ca_file_tstr) { - char buffer[STRERROR_LEN]; + char buffer[WINAPI_ERROR_LEN]; failf(data, "schannel: invalid path name for CA file '%s': %s", ca_file, @@ -273,7 +274,7 @@ static CURLcode add_certs_file_to_store(HCERTSTORE trust_store, FILE_ATTRIBUTE_NORMAL, NULL); if(ca_file_handle == INVALID_HANDLE_VALUE) { - char buffer[STRERROR_LEN]; + char buffer[WINAPI_ERROR_LEN]; failf(data, "schannel: failed to open CA file '%s': %s", ca_file, @@ -283,7 +284,7 @@ static CURLcode add_certs_file_to_store(HCERTSTORE trust_store, } if(!GetFileSizeEx(ca_file_handle, &file_size)) { - char buffer[STRERROR_LEN]; + char buffer[WINAPI_ERROR_LEN]; failf(data, "schannel: failed to determine size of CA file '%s': %s", ca_file, @@ -313,7 +314,7 @@ static CURLcode add_certs_file_to_store(HCERTSTORE trust_store, if(!ReadFile(ca_file_handle, ca_file_buffer + total_bytes_read, bytes_to_read, &bytes_read, NULL)) { - char buffer[STRERROR_LEN]; + char buffer[WINAPI_ERROR_LEN]; failf(data, "schannel: failed to read from CA file '%s': %s", ca_file, @@ -614,7 +615,7 @@ CURLcode Curl_verify_host(struct Curl_cfilter *cf, &pCertContextServer); if((sspi_status != SEC_E_OK) || !pCertContextServer) { - char buffer[STRERROR_LEN]; + char buffer[WINAPI_ERROR_LEN]; failf(data, "schannel: Failed to read remote certificate context: %s", Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); goto cleanup; @@ -770,7 +771,7 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf, &pCertContextServer); if((sspi_status != SEC_E_OK) || !pCertContextServer) { - char buffer[STRERROR_LEN]; + char buffer[WINAPI_ERROR_LEN]; failf(data, "schannel: Failed to read remote certificate context: %s", Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); result = CURLE_PEER_FAILED_VERIFICATION; @@ -806,7 +807,7 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf, CERT_STORE_CREATE_NEW_FLAG, NULL); if(!trust_store) { - char buffer[STRERROR_LEN]; + char buffer[WINAPI_ERROR_LEN]; failf(data, "schannel: failed to create certificate store: %s", curlx_winapi_strerror(GetLastError(), buffer, sizeof(buffer))); result = CURLE_SSL_CACERT_BADFILE; @@ -853,7 +854,7 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf, CertCreateCertificateChainEngine( (CERT_CHAIN_ENGINE_CONFIG *)&engine_config, &cert_chain_engine); if(!create_engine_result) { - char buffer[STRERROR_LEN]; + char buffer[WINAPI_ERROR_LEN]; failf(data, "schannel: failed to create certificate chain engine: %s", curlx_winapi_strerror(GetLastError(), buffer, sizeof(buffer))); @@ -878,7 +879,7 @@ CURLcode Curl_verify_certificate(struct Curl_cfilter *cf, CERT_CHAIN_REVOCATION_CHECK_CHAIN), NULL, &pChainContext)) { - char buffer[STRERROR_LEN]; + char buffer[WINAPI_ERROR_LEN]; failf(data, "schannel: CertGetCertificateChain failed: %s", curlx_winapi_strerror(GetLastError(), buffer, sizeof(buffer))); pChainContext = NULL; diff --git a/tests/server/Makefile.inc b/tests/server/Makefile.inc index e5c6345baa..a4e26a529e 100644 --- a/tests/server/Makefile.inc +++ b/tests/server/Makefile.inc @@ -62,8 +62,8 @@ UTIL = \ server_setup.h \ ../../lib/curlx/base64.c \ ../../lib/curlx/base64.h \ - ../../lib/strerror.c \ - ../../lib/strerror.h + ../../lib/curlx/winapi.c \ + ../../lib/curlx/winapi.h FIRSTFILES = \ first.c \ diff --git a/tests/server/util.c b/tests/server/util.c index f884cf8f6c..d274baf161 100644 --- a/tests/server/util.c +++ b/tests/server/util.c @@ -41,10 +41,6 @@ #include /* delay() */ #endif -#ifdef _WIN32 -#include "strerror.h" -#endif - #include /* from the private lib dir */ #include "util.h"