From 132cbe42e1e22f209a72863ab847504428c3ca4b Mon Sep 17 00:00:00 2001 From: Marcel Raad Date: Thu, 23 Jul 2020 21:28:14 +0200 Subject: [PATCH] WIN32: stop forcing narrow-character API Except where the results are only used for character output or with hardcoded string literals. Fixes https://github.com/curl/curl/issues/5658 Fixes https://github.com/curl/curl/issues/5712 Closes --- lib/getenv.c | 20 ++++++++++++++------ lib/rename.c | 15 ++++++++++++--- src/tool_doswin.c | 19 ++++++++++++------- src/tool_doswin.h | 2 +- src/tool_filetime.c | 11 +++++++++-- src/tool_operate.c | 2 +- 6 files changed, 49 insertions(+), 20 deletions(-) diff --git a/lib/getenv.c b/lib/getenv.c index 9385b8f677f539..a5e4c0a1f253bc 100644 --- a/lib/getenv.c +++ b/lib/getenv.c @@ -23,6 +23,7 @@ #include "curl_setup.h" #include +#include "curl_multibyte.h" #include "curl_memory.h" #include "memdebug.h" @@ -35,16 +36,18 @@ static char *GetEnv(const char *variable) #elif defined(WIN32) /* This uses Windows API instead of C runtime getenv() to get the environment variable since some changes aren't always visible to the latter. #4774 */ - char *buf = NULL; - char *tmp; + TCHAR *buf = NULL; + TCHAR *tmp; DWORD bufsize; DWORD rc = 1; const DWORD max = 32768; /* max env var size from MSCRT source */ + TCHAR *tchar_envvar = curlx_convert_UTF8_to_tchar((char *)variable); for(;;) { - tmp = realloc(buf, rc); + tmp = realloc(buf, rc * sizeof(TCHAR)); if(!tmp) { free(buf); + curlx_unicodefree(tchar_envvar); return NULL; } @@ -53,15 +56,20 @@ static char *GetEnv(const char *variable) /* It's possible for rc to be 0 if the variable was found but empty. Since getenv doesn't make that distinction we ignore it as well. */ - rc = GetEnvironmentVariableA(variable, buf, bufsize); + rc = GetEnvironmentVariable(tchar_envvar, buf, bufsize); if(!rc || rc == bufsize || rc > max) { free(buf); + curlx_unicodefree(tchar_envvar); return NULL; } /* if rc < bufsize then rc is bytes written not including null */ - if(rc < bufsize) - return buf; + if(rc < bufsize) { + char *path = curlx_convert_tchar_to_UTF8(buf); + curlx_unicodefree(buf); + curlx_unicodefree(tchar_envvar); + return path; + } /* else rc is bytes needed, try again */ } diff --git a/lib/rename.c b/lib/rename.c index bb170d3cc7bc7b..fe5f95d0dfd0f2 100644 --- a/lib/rename.c +++ b/lib/rename.c @@ -27,6 +27,7 @@ #if (!defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)) || \ defined(USE_ALTSVC) +#include "curl_multibyte.h" #include "timeval.h" /* The last 3 #include files should be in this order */ @@ -39,17 +40,25 @@ int Curl_rename(const char *oldpath, const char *newpath) { #ifdef WIN32 /* rename() on Windows doesn't overwrite, so we can't use it here. - MoveFileExA() will overwrite and is usually atomic, however it fails + MoveFileEx() will overwrite and is usually atomic, however it fails when there are open handles to the file. */ const int max_wait_ms = 1000; struct curltime start = Curl_now(); + TCHAR *tchar_oldpath = curlx_convert_UTF8_to_tchar((char *)oldpath); + TCHAR *tchar_newpath = curlx_convert_UTF8_to_tchar((char *)newpath); for(;;) { timediff_t diff; - if(MoveFileExA(oldpath, newpath, MOVEFILE_REPLACE_EXISTING)) + if(MoveFileEx(tchar_oldpath, tchar_newpath, MOVEFILE_REPLACE_EXISTING)) { + curlx_unicodefree(tchar_oldpath); + curlx_unicodefree(tchar_newpath); break; + } diff = Curl_timediff(Curl_now(), start); - if(diff < 0 || diff > max_wait_ms) + if(diff < 0 || diff > max_wait_ms) { + curlx_unicodefree(tchar_oldpath); + curlx_unicodefree(tchar_newpath); return 1; + } Sleep(1); } #else diff --git a/src/tool_doswin.c b/src/tool_doswin.c index b7df3e6155cd7d..78285a21b027fd 100644 --- a/src/tool_doswin.c +++ b/src/tool_doswin.c @@ -36,6 +36,7 @@ #include "tool_bname.h" #include "tool_doswin.h" +#include "curlx.h" #include "memdebug.h" /* keep this as LAST include */ #ifdef WIN32 @@ -612,7 +613,7 @@ char **__crt0_glob_function(char *arg) CURLcode FindWin32CACert(struct OperationConfig *config, curl_sslbackend backend, - const char *bundle_file) + const TCHAR *bundle_file) { CURLcode result = CURLE_OK; @@ -626,15 +627,19 @@ CURLcode FindWin32CACert(struct OperationConfig *config, backend != CURLSSLBACKEND_SCHANNEL) { DWORD res_len; - char buf[PATH_MAX]; - char *ptr = NULL; + TCHAR buf[PATH_MAX]; + TCHAR *ptr = NULL; - buf[0] = '\0'; + buf[0] = TEXT('\0'); - res_len = SearchPathA(NULL, bundle_file, NULL, PATH_MAX, buf, &ptr); + res_len = SearchPath(NULL, bundle_file, NULL, PATH_MAX, buf, &ptr); if(res_len > 0) { Curl_safefree(config->cacert); +#ifdef UNICODE + config->cacert = curlx_convert_wchar_to_UTF8(buf); +#else config->cacert = strdup(buf); +#endif if(!config->cacert) result = CURLE_OUT_OF_MEMORY; } @@ -702,7 +707,7 @@ bool tool_isVistaOrGreater; CURLcode win32_init(void) { - OSVERSIONINFOEXA osvi; + OSVERSIONINFOEX osvi; unsigned __int64 mask = 0; unsigned char op = VER_GREATER_EQUAL; @@ -712,7 +717,7 @@ CURLcode win32_init(void) VER_SET_CONDITION(mask, VER_MAJORVERSION, op); VER_SET_CONDITION(mask, VER_MINORVERSION, op); - if(VerifyVersionInfoA(&osvi, (VER_MAJORVERSION | VER_MINORVERSION), mask)) + if(VerifyVersionInfo(&osvi, (VER_MAJORVERSION | VER_MINORVERSION), mask)) tool_isVistaOrGreater = true; else if(GetLastError() == ERROR_OLD_WIN_VERSION) tool_isVistaOrGreater = false; diff --git a/src/tool_doswin.h b/src/tool_doswin.h index d1649d1f3fcd14..ab23f8d65ef25c 100644 --- a/src/tool_doswin.h +++ b/src/tool_doswin.h @@ -59,7 +59,7 @@ char **__crt0_glob_function(char *arg); CURLcode FindWin32CACert(struct OperationConfig *config, curl_sslbackend backend, - const char *bundle_file); + const TCHAR *bundle_file); struct curl_slist *GetLoadedModulePaths(void); CURLcode win32_init(void); diff --git a/src/tool_filetime.c b/src/tool_filetime.c index 6071e44d214e39..075ef3e876d39f 100644 --- a/src/tool_filetime.c +++ b/src/tool_filetime.c @@ -21,6 +21,8 @@ ***************************************************************************/ #include "tool_filetime.h" +#include "curlx.h" + #ifdef HAVE_UTIME_H # include #elif defined(HAVE_SYS_UTIME_H) @@ -36,11 +38,13 @@ curl_off_t getfiletime(const char *filename, FILE *error_stream) access to a 64-bit type we can bypass stat and get the times directly. */ #if defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8) HANDLE hfile; + TCHAR *filename_tchar = curlx_convert_UTF8_to_tchar((char *)filename); - hfile = CreateFileA(filename, FILE_READ_ATTRIBUTES, + hfile = CreateFile(filename_tchar, FILE_READ_ATTRIBUTES, (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE), NULL, OPEN_EXISTING, 0, NULL); + curlx_unicodefree(filename_tchar); if(hfile != INVALID_HANDLE_VALUE) { FILETIME ft; if(GetFileTime(hfile, NULL, NULL, &ft)) { @@ -93,6 +97,7 @@ void setfiletime(curl_off_t filetime, const char *filename, access to a 64-bit type we can bypass utime and set the times directly. */ #if defined(WIN32) && (SIZEOF_CURL_OFF_T >= 8) HANDLE hfile; + TCHAR *filename_tchar = curlx_convert_UTF8_to_tchar((char *)filename); /* 910670515199 is the maximum unix filetime that can be used as a Windows FILETIME without overflow: 30827-12-31T23:59:59. */ @@ -100,13 +105,15 @@ void setfiletime(curl_off_t filetime, const char *filename, fprintf(error_stream, "Failed to set filetime %" CURL_FORMAT_CURL_OFF_T " on outfile: overflow\n", filetime); + curlx_unicodefree(filename_tchar); return; } - hfile = CreateFileA(filename, FILE_WRITE_ATTRIBUTES, + hfile = CreateFile(filename_tchar, FILE_WRITE_ATTRIBUTES, (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE), NULL, OPEN_EXISTING, 0, NULL); + curlx_unicodefree(filename_tchar); if(hfile != INVALID_HANDLE_VALUE) { curl_off_t converted = ((curl_off_t)filetime * 10000000) + CURL_OFF_T_C(116444736000000000); diff --git a/src/tool_operate.c b/src/tool_operate.c index 29daff02a43d9c..ad4e85dd83eb89 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -2415,7 +2415,7 @@ static CURLcode transfer_per_config(struct GlobalConfig *global, #ifdef WIN32 else { result = FindWin32CACert(config, tls_backend_info->backend, - "curl-ca-bundle.crt"); + TEXT("curl-ca-bundle.crt")); } #endif }