curl_multibyte: add to curlx

This will also be needed in the tool and tests.

Ref: https://github.com/curl/curl/pull/3758#issuecomment-482197512
Closes https://github.com/curl/curl/pull/3784
This commit is contained in:
Marcel Raad 2019-04-13 22:55:51 +02:00
parent 600a8cded4
commit a55c835e6b
No known key found for this signature in database
GPG Key ID: 33C416EFAE4D6F02
16 changed files with 128 additions and 119 deletions

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -20,24 +20,21 @@
* *
***************************************************************************/ ***************************************************************************/
/*
* This file is 'mem-include-scan' clean. See test 1132.
*/
#include "curl_setup.h" #include "curl_setup.h"
#include <curl/curl.h> #if defined(WIN32)
#if defined(USE_WIN32_IDN) || ((defined(USE_WINDOWS_SSPI) || \
defined(USE_WIN32_LDAP)) && defined(UNICODE))
/*
* MultiByte conversions using Windows kernel32 library.
*/
#include "curl_multibyte.h" #include "curl_multibyte.h"
#include "curl_memory.h"
/* The last #include file should be: */ /*
#include "memdebug.h" * MultiByte conversions using Windows kernel32 library.
*/
wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8) wchar_t *curlx_convert_UTF8_to_wchar(const char *str_utf8)
{ {
wchar_t *str_w = NULL; wchar_t *str_w = NULL;
@ -59,7 +56,7 @@ wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8)
return str_w; return str_w;
} }
char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w) char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w)
{ {
char *str_utf8 = NULL; char *str_utf8 = NULL;
@ -81,4 +78,4 @@ char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w)
return str_utf8; return str_utf8;
} }
#endif /* USE_WIN32_IDN || ((USE_WINDOWS_SSPI || USE_WIN32_LDAP) && UNICODE) */ #endif /* WIN32 */

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -23,48 +23,43 @@
***************************************************************************/ ***************************************************************************/
#include "curl_setup.h" #include "curl_setup.h"
#if defined(USE_WIN32_IDN) || ((defined(USE_WINDOWS_SSPI) || \ #if defined(WIN32)
defined(USE_WIN32_LDAP)) && defined(UNICODE))
/* /*
* MultiByte conversions using Windows kernel32 library. * MultiByte conversions using Windows kernel32 library.
*/ */
wchar_t *Curl_convert_UTF8_to_wchar(const char *str_utf8); wchar_t *curlx_convert_UTF8_to_wchar(const char *str_utf8);
char *Curl_convert_wchar_to_UTF8(const wchar_t *str_w); char *curlx_convert_wchar_to_UTF8(const wchar_t *str_w);
#endif /* USE_WIN32_IDN || ((USE_WINDOWS_SSPI || USE_WIN32_LDAP) && UNICODE) */ #endif /* WIN32 */
#if defined(USE_WIN32_IDN) || defined(USE_WINDOWS_SSPI) || \
defined(USE_WIN32_LDAP)
/* /*
* Macros Curl_convert_UTF8_to_tchar(), Curl_convert_tchar_to_UTF8() * Macros curlx_convert_UTF8_to_tchar(), curlx_convert_tchar_to_UTF8()
* and Curl_unicodefree() main purpose is to minimize the number of * and curlx_unicodefree() main purpose is to minimize the number of
* preprocessor conditional directives needed by code using these * preprocessor conditional directives needed by code using these
* to differentiate UNICODE from non-UNICODE builds. * to differentiate UNICODE from non-UNICODE builds.
* *
* When building with UNICODE defined, this two macros * When building with UNICODE defined, these two macros
* Curl_convert_UTF8_to_tchar() and Curl_convert_tchar_to_UTF8() * curlx_convert_UTF8_to_tchar() and curlx_convert_tchar_to_UTF8()
* return a pointer to a newly allocated memory area holding result. * return a pointer to a newly allocated memory area holding result.
* When the result is no longer needed, allocated memory is intended * When the result is no longer needed, allocated memory is intended
* to be free'ed with Curl_unicodefree(). * to be free'ed with curlx_unicodefree().
* *
* When building without UNICODE defined, this macros * When building without UNICODE defined, this macros
* Curl_convert_UTF8_to_tchar() and Curl_convert_tchar_to_UTF8() * curlx_convert_UTF8_to_tchar() and curlx_convert_tchar_to_UTF8()
* return the pointer received as argument. Curl_unicodefree() does * return the pointer received as argument. curlx_unicodefree() does
* no actual free'ing of this pointer it is simply set to NULL. * no actual free'ing of this pointer it is simply set to NULL.
*/ */
#ifdef UNICODE #if defined(UNICODE) && defined(WIN32)
#define Curl_convert_UTF8_to_tchar(ptr) Curl_convert_UTF8_to_wchar((ptr)) #define curlx_convert_UTF8_to_tchar(ptr) curlx_convert_UTF8_to_wchar((ptr))
#define Curl_convert_tchar_to_UTF8(ptr) Curl_convert_wchar_to_UTF8((ptr)) #define curlx_convert_tchar_to_UTF8(ptr) curlx_convert_wchar_to_UTF8((ptr))
#define Curl_unicodefree(ptr) \ #define curlx_unicodefree(ptr) \
do { \ do { \
if(ptr) { \ if(ptr) { \
free(ptr); \ (free)(ptr); \
(ptr) = NULL; \ (ptr) = NULL; \
} \ } \
} while(0) } while(0)
@ -78,9 +73,9 @@ typedef union {
#else #else
#define Curl_convert_UTF8_to_tchar(ptr) (ptr) #define curlx_convert_UTF8_to_tchar(ptr) (ptr)
#define Curl_convert_tchar_to_UTF8(ptr) (ptr) #define curlx_convert_tchar_to_UTF8(ptr) (ptr)
#define Curl_unicodefree(ptr) \ #define curlx_unicodefree(ptr) \
do {(ptr) = NULL;} while(0) do {(ptr) = NULL;} while(0)
typedef union { typedef union {
@ -90,8 +85,6 @@ typedef union {
const unsigned char *const_tbyte_ptr; const unsigned char *const_tbyte_ptr;
} xcharp_u; } xcharp_u;
#endif /* UNICODE */ #endif /* UNICODE && WIN32 */
#endif /* USE_WIN32_IDN || USE_WINDOWS_SSPI || USE_WIN32_LDAP */
#endif /* HEADER_CURL_MULTIBYTE_H */ #endif /* HEADER_CURL_MULTIBYTE_H */

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -151,7 +151,7 @@ CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
/* Initialize the identity */ /* Initialize the identity */
memset(identity, 0, sizeof(*identity)); memset(identity, 0, sizeof(*identity));
useranddomain.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)userp); useranddomain.tchar_ptr = curlx_convert_UTF8_to_tchar((char *)userp);
if(!useranddomain.tchar_ptr) if(!useranddomain.tchar_ptr)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
@ -173,7 +173,7 @@ CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
/* Setup the identity's user and length */ /* Setup the identity's user and length */
dup_user.tchar_ptr = _tcsdup(user.tchar_ptr); dup_user.tchar_ptr = _tcsdup(user.tchar_ptr);
if(!dup_user.tchar_ptr) { if(!dup_user.tchar_ptr) {
Curl_unicodefree(useranddomain.tchar_ptr); curlx_unicodefree(useranddomain.tchar_ptr);
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
identity->User = dup_user.tbyte_ptr; identity->User = dup_user.tbyte_ptr;
@ -183,7 +183,7 @@ CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
/* Setup the identity's domain and length */ /* Setup the identity's domain and length */
dup_domain.tchar_ptr = malloc(sizeof(TCHAR) * (domlen + 1)); dup_domain.tchar_ptr = malloc(sizeof(TCHAR) * (domlen + 1));
if(!dup_domain.tchar_ptr) { if(!dup_domain.tchar_ptr) {
Curl_unicodefree(useranddomain.tchar_ptr); curlx_unicodefree(useranddomain.tchar_ptr);
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
_tcsncpy(dup_domain.tchar_ptr, domain.tchar_ptr, domlen); _tcsncpy(dup_domain.tchar_ptr, domain.tchar_ptr, domlen);
@ -192,22 +192,22 @@ CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
identity->DomainLength = curlx_uztoul(domlen); identity->DomainLength = curlx_uztoul(domlen);
dup_domain.tchar_ptr = NULL; dup_domain.tchar_ptr = NULL;
Curl_unicodefree(useranddomain.tchar_ptr); curlx_unicodefree(useranddomain.tchar_ptr);
/* Setup the identity's password and length */ /* Setup the identity's password and length */
passwd.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)passwdp); passwd.tchar_ptr = curlx_convert_UTF8_to_tchar((char *)passwdp);
if(!passwd.tchar_ptr) if(!passwd.tchar_ptr)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
dup_passwd.tchar_ptr = _tcsdup(passwd.tchar_ptr); dup_passwd.tchar_ptr = _tcsdup(passwd.tchar_ptr);
if(!dup_passwd.tchar_ptr) { if(!dup_passwd.tchar_ptr) {
Curl_unicodefree(passwd.tchar_ptr); curlx_unicodefree(passwd.tchar_ptr);
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
identity->Password = dup_passwd.tbyte_ptr; identity->Password = dup_passwd.tbyte_ptr;
identity->PasswordLength = curlx_uztoul(_tcslen(dup_passwd.tchar_ptr)); identity->PasswordLength = curlx_uztoul(_tcslen(dup_passwd.tchar_ptr));
dup_passwd.tchar_ptr = NULL; dup_passwd.tchar_ptr = NULL;
Curl_unicodefree(passwd.tchar_ptr); curlx_unicodefree(passwd.tchar_ptr);
/* Setup the identity's flags */ /* Setup the identity's flags */
identity->Flags = SECFLAG_WINNT_AUTH_IDENTITY; identity->Flags = SECFLAG_WINNT_AUTH_IDENTITY;

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2018, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -53,6 +53,16 @@
curlx_uztosi() curlx_uztosi()
*/ */
#include "curl_multibyte.h"
/* "curl_multibyte.h" provides these functions and macros:
curlx_convert_UTF8_to_wchar()
curlx_convert_wchar_to_UTF8()
curlx_convert_UTF8_to_tchar()
curlx_convert_tchar_to_UTF8()
curlx_unicodefree()
*/
/* Now setup curlx_ * names for the functions that are to become curlx_ and /* Now setup curlx_ * names for the functions that are to become curlx_ and
be removed from a future libcurl official API: be removed from a future libcurl official API:
curlx_getenv curlx_getenv

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -72,13 +72,13 @@ bool curl_win32_idn_to_ascii(const char *in, char **out)
{ {
bool success = FALSE; bool success = FALSE;
wchar_t *in_w = Curl_convert_UTF8_to_wchar(in); wchar_t *in_w = curlx_convert_UTF8_to_wchar(in);
if(in_w) { if(in_w) {
wchar_t punycode[IDN_MAX_LENGTH]; wchar_t punycode[IDN_MAX_LENGTH];
int chars = IdnToAscii(0, in_w, -1, punycode, IDN_MAX_LENGTH); int chars = IdnToAscii(0, in_w, -1, punycode, IDN_MAX_LENGTH);
free(in_w); free(in_w);
if(chars) { if(chars) {
*out = Curl_convert_wchar_to_UTF8(punycode); *out = curlx_convert_wchar_to_UTF8(punycode);
if(*out) if(*out)
success = TRUE; success = TRUE;
} }
@ -91,7 +91,7 @@ bool curl_win32_ascii_to_idn(const char *in, char **out)
{ {
bool success = FALSE; bool success = FALSE;
wchar_t *in_w = Curl_convert_UTF8_to_wchar(in); wchar_t *in_w = curlx_convert_UTF8_to_wchar(in);
if(in_w) { if(in_w) {
size_t in_len = wcslen(in_w) + 1; size_t in_len = wcslen(in_w) + 1;
wchar_t unicode[IDN_MAX_LENGTH]; wchar_t unicode[IDN_MAX_LENGTH];
@ -99,7 +99,7 @@ bool curl_win32_ascii_to_idn(const char *in, char **out)
unicode, IDN_MAX_LENGTH); unicode, IDN_MAX_LENGTH);
free(in_w); free(in_w);
if(chars) { if(chars) {
*out = Curl_convert_wchar_to_UTF8(unicode); *out = curlx_convert_wchar_to_UTF8(unicode);
if(*out) if(*out)
success = TRUE; success = TRUE;
} }

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___ * | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -239,13 +239,13 @@ static int ldap_win_bind(struct connectdata *conn, LDAP *server,
PTCHAR inpass = NULL; PTCHAR inpass = NULL;
if(user && passwd && (conn->data->set.httpauth & CURLAUTH_BASIC)) { if(user && passwd && (conn->data->set.httpauth & CURLAUTH_BASIC)) {
inuser = Curl_convert_UTF8_to_tchar((char *) user); inuser = curlx_convert_UTF8_to_tchar((char *) user);
inpass = Curl_convert_UTF8_to_tchar((char *) passwd); inpass = curlx_convert_UTF8_to_tchar((char *) passwd);
rc = ldap_simple_bind_s(server, inuser, inpass); rc = ldap_simple_bind_s(server, inuser, inpass);
Curl_unicodefree(inuser); curlx_unicodefree(inuser);
Curl_unicodefree(inpass); curlx_unicodefree(inpass);
} }
#if defined(USE_WINDOWS_SSPI) #if defined(USE_WINDOWS_SSPI)
else { else {
@ -306,7 +306,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
ldap_ssl ? "encrypted" : "cleartext"); ldap_ssl ? "encrypted" : "cleartext");
#if defined(USE_WIN32_LDAP) #if defined(USE_WIN32_LDAP)
host = Curl_convert_UTF8_to_tchar(conn->host.name); host = curlx_convert_UTF8_to_tchar(conn->host.name);
if(!host) { if(!host) {
result = CURLE_OUT_OF_MEMORY; result = CURLE_OUT_OF_MEMORY;
@ -517,7 +517,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
size_t name_len; size_t name_len;
#if defined(USE_WIN32_LDAP) #if defined(USE_WIN32_LDAP)
TCHAR *dn = ldap_get_dn(server, entryIterator); TCHAR *dn = ldap_get_dn(server, entryIterator);
name = Curl_convert_tchar_to_UTF8(dn); name = curlx_convert_tchar_to_UTF8(dn);
if(!name) { if(!name) {
ldap_memfree(dn); ldap_memfree(dn);
@ -533,7 +533,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4); result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4);
if(result) { if(result) {
#if defined(USE_WIN32_LDAP) #if defined(USE_WIN32_LDAP)
Curl_unicodefree(name); curlx_unicodefree(name);
#endif #endif
ldap_memfree(dn); ldap_memfree(dn);
@ -544,7 +544,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
name_len); name_len);
if(result) { if(result) {
#if defined(USE_WIN32_LDAP) #if defined(USE_WIN32_LDAP)
Curl_unicodefree(name); curlx_unicodefree(name);
#endif #endif
ldap_memfree(dn); ldap_memfree(dn);
@ -554,7 +554,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1); result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
if(result) { if(result) {
#if defined(USE_WIN32_LDAP) #if defined(USE_WIN32_LDAP)
Curl_unicodefree(name); curlx_unicodefree(name);
#endif #endif
ldap_memfree(dn); ldap_memfree(dn);
@ -564,7 +564,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
dlsize += name_len + 5; dlsize += name_len + 5;
#if defined(USE_WIN32_LDAP) #if defined(USE_WIN32_LDAP)
Curl_unicodefree(name); curlx_unicodefree(name);
#endif #endif
ldap_memfree(dn); ldap_memfree(dn);
} }
@ -576,7 +576,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
BerValue **vals; BerValue **vals;
size_t attr_len; size_t attr_len;
#if defined(USE_WIN32_LDAP) #if defined(USE_WIN32_LDAP)
char *attr = Curl_convert_tchar_to_UTF8(attribute); char *attr = curlx_convert_tchar_to_UTF8(attribute);
if(!attr) { if(!attr) {
if(ber) if(ber)
ber_free(ber, 0); ber_free(ber, 0);
@ -597,7 +597,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
if(result) { if(result) {
ldap_value_free_len(vals); ldap_value_free_len(vals);
#if defined(USE_WIN32_LDAP) #if defined(USE_WIN32_LDAP)
Curl_unicodefree(attr); curlx_unicodefree(attr);
#endif #endif
ldap_memfree(attribute); ldap_memfree(attribute);
if(ber) if(ber)
@ -611,7 +611,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
if(result) { if(result) {
ldap_value_free_len(vals); ldap_value_free_len(vals);
#if defined(USE_WIN32_LDAP) #if defined(USE_WIN32_LDAP)
Curl_unicodefree(attr); curlx_unicodefree(attr);
#endif #endif
ldap_memfree(attribute); ldap_memfree(attribute);
if(ber) if(ber)
@ -624,7 +624,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
if(result) { if(result) {
ldap_value_free_len(vals); ldap_value_free_len(vals);
#if defined(USE_WIN32_LDAP) #if defined(USE_WIN32_LDAP)
Curl_unicodefree(attr); curlx_unicodefree(attr);
#endif #endif
ldap_memfree(attribute); ldap_memfree(attribute);
if(ber) if(ber)
@ -646,7 +646,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
if(result) { if(result) {
ldap_value_free_len(vals); ldap_value_free_len(vals);
#if defined(USE_WIN32_LDAP) #if defined(USE_WIN32_LDAP)
Curl_unicodefree(attr); curlx_unicodefree(attr);
#endif #endif
ldap_memfree(attribute); ldap_memfree(attribute);
if(ber) if(ber)
@ -662,7 +662,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
if(result) { if(result) {
ldap_value_free_len(vals); ldap_value_free_len(vals);
#if defined(USE_WIN32_LDAP) #if defined(USE_WIN32_LDAP)
Curl_unicodefree(attr); curlx_unicodefree(attr);
#endif #endif
ldap_memfree(attribute); ldap_memfree(attribute);
if(ber) if(ber)
@ -680,7 +680,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
if(result) { if(result) {
ldap_value_free_len(vals); ldap_value_free_len(vals);
#if defined(USE_WIN32_LDAP) #if defined(USE_WIN32_LDAP)
Curl_unicodefree(attr); curlx_unicodefree(attr);
#endif #endif
ldap_memfree(attribute); ldap_memfree(attribute);
if(ber) if(ber)
@ -696,7 +696,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
if(result) { if(result) {
ldap_value_free_len(vals); ldap_value_free_len(vals);
#if defined(USE_WIN32_LDAP) #if defined(USE_WIN32_LDAP)
Curl_unicodefree(attr); curlx_unicodefree(attr);
#endif #endif
ldap_memfree(attribute); ldap_memfree(attribute);
if(ber) if(ber)
@ -714,7 +714,7 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
/* Free the attribute as we are done with it */ /* Free the attribute as we are done with it */
#if defined(USE_WIN32_LDAP) #if defined(USE_WIN32_LDAP)
Curl_unicodefree(attr); curlx_unicodefree(attr);
#endif #endif
ldap_memfree(attribute); ldap_memfree(attribute);
@ -746,7 +746,7 @@ quit:
#endif /* HAVE_LDAP_SSL && CURL_HAS_NOVELL_LDAPSDK */ #endif /* HAVE_LDAP_SSL && CURL_HAS_NOVELL_LDAPSDK */
#if defined(USE_WIN32_LDAP) #if defined(USE_WIN32_LDAP)
Curl_unicodefree(host); curlx_unicodefree(host);
#endif #endif
/* no data to transfer */ /* no data to transfer */
@ -892,10 +892,10 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
#if defined(USE_WIN32_LDAP) #if defined(USE_WIN32_LDAP)
/* Convert the unescaped string to a tchar */ /* Convert the unescaped string to a tchar */
ludp->lud_dn = Curl_convert_UTF8_to_tchar(unescaped); ludp->lud_dn = curlx_convert_UTF8_to_tchar(unescaped);
/* Free the unescaped string as we are done with it */ /* Free the unescaped string as we are done with it */
Curl_unicodefree(unescaped); curlx_unicodefree(unescaped);
if(!ludp->lud_dn) { if(!ludp->lud_dn) {
rc = LDAP_NO_MEMORY; rc = LDAP_NO_MEMORY;
@ -960,10 +960,10 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
#if defined(USE_WIN32_LDAP) #if defined(USE_WIN32_LDAP)
/* Convert the unescaped string to a tchar */ /* Convert the unescaped string to a tchar */
ludp->lud_attrs[i] = Curl_convert_UTF8_to_tchar(unescaped); ludp->lud_attrs[i] = curlx_convert_UTF8_to_tchar(unescaped);
/* Free the unescaped string as we are done with it */ /* Free the unescaped string as we are done with it */
Curl_unicodefree(unescaped); curlx_unicodefree(unescaped);
if(!ludp->lud_attrs[i]) { if(!ludp->lud_attrs[i]) {
free(attributes); free(attributes);
@ -1027,10 +1027,10 @@ static int _ldap_url_parse2(const struct connectdata *conn, LDAPURLDesc *ludp)
#if defined(USE_WIN32_LDAP) #if defined(USE_WIN32_LDAP)
/* Convert the unescaped string to a tchar */ /* Convert the unescaped string to a tchar */
ludp->lud_filter = Curl_convert_UTF8_to_tchar(unescaped); ludp->lud_filter = curlx_convert_UTF8_to_tchar(unescaped);
/* Free the unescaped string as we are done with it */ /* Free the unescaped string as we are done with it */
Curl_unicodefree(unescaped); curlx_unicodefree(unescaped);
if(!ludp->lud_filter) { if(!ludp->lud_filter) {
rc = LDAP_NO_MEMORY; rc = LDAP_NO_MEMORY;

View File

@ -160,7 +160,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
for(;;) { for(;;) {
TCHAR *sname; TCHAR *sname;
sname = Curl_convert_UTF8_to_tchar(service_name); sname = curlx_convert_UTF8_to_tchar(service_name);
if(!sname) if(!sname)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
@ -180,7 +180,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
&sspi_ret_flags, &sspi_ret_flags,
&expiry); &expiry);
Curl_unicodefree(sname); curlx_unicodefree(sname);
if(sspi_recv_token.pvBuffer) { if(sspi_recv_token.pvBuffer) {
s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer); s_pSecFn->FreeContextBuffer(sspi_recv_token.pvBuffer);

View File

@ -6,7 +6,7 @@
* \___|\___/|_| \_\_____| * \___|\___/|_| \_\_____|
* *
* Copyright (C) 2014 - 2016, Steve Holme, <steve_holme@hotmail.com>. * Copyright (C) 2014 - 2016, Steve Holme, <steve_holme@hotmail.com>.
* Copyright (C) 2015 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al. * Copyright (C) 2015 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
* *
* This software is licensed as described in the file COPYING, which * This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms * you should have received as part of this distribution. The terms
@ -289,13 +289,13 @@ CURLcode Curl_override_sspi_http_realm(const char *chlg,
if(strcasecompare(value, "realm")) { if(strcasecompare(value, "realm")) {
/* Setup identity's domain and length */ /* Setup identity's domain and length */
domain.tchar_ptr = Curl_convert_UTF8_to_tchar((char *) content); domain.tchar_ptr = curlx_convert_UTF8_to_tchar((char *) content);
if(!domain.tchar_ptr) if(!domain.tchar_ptr)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
dup_domain.tchar_ptr = _tcsdup(domain.tchar_ptr); dup_domain.tchar_ptr = _tcsdup(domain.tchar_ptr);
if(!dup_domain.tchar_ptr) { if(!dup_domain.tchar_ptr) {
Curl_unicodefree(domain.tchar_ptr); curlx_unicodefree(domain.tchar_ptr);
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
@ -304,7 +304,7 @@ CURLcode Curl_override_sspi_http_realm(const char *chlg,
identity->DomainLength = curlx_uztoul(_tcslen(dup_domain.tchar_ptr)); identity->DomainLength = curlx_uztoul(_tcslen(dup_domain.tchar_ptr));
dup_domain.tchar_ptr = NULL; dup_domain.tchar_ptr = NULL;
Curl_unicodefree(domain.tchar_ptr); curlx_unicodefree(domain.tchar_ptr);
} }
else { else {
/* Unknown specifier, ignore it! */ /* Unknown specifier, ignore it! */
@ -583,7 +583,7 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
resp_buf.pvBuffer = output_token; resp_buf.pvBuffer = output_token;
resp_buf.cbBuffer = curlx_uztoul(token_max); resp_buf.cbBuffer = curlx_uztoul(token_max);
spn = Curl_convert_UTF8_to_tchar((char *) uripath); spn = curlx_convert_UTF8_to_tchar((char *) uripath);
if(!spn) { if(!spn) {
s_pSecFn->FreeCredentialsHandle(&credentials); s_pSecFn->FreeCredentialsHandle(&credentials);
@ -605,7 +605,7 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
&chlg_desc, 0, &chlg_desc, 0,
digest->http_context, digest->http_context,
&resp_desc, &attrs, &expiry); &resp_desc, &attrs, &expiry);
Curl_unicodefree(spn); curlx_unicodefree(spn);
if(status == SEC_I_COMPLETE_NEEDED || if(status == SEC_I_COMPLETE_NEEDED ||
status == SEC_I_COMPLETE_AND_CONTINUE) status == SEC_I_COMPLETE_AND_CONTINUE)

View File

@ -396,7 +396,7 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
/* Convert the user name to UTF8 when operating with Unicode */ /* Convert the user name to UTF8 when operating with Unicode */
user_name = Curl_convert_tchar_to_UTF8(names.sUserName); user_name = curlx_convert_tchar_to_UTF8(names.sUserName);
if(!user_name) { if(!user_name) {
free(trailer); free(trailer);
@ -408,7 +408,7 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
message = malloc(messagelen); message = malloc(messagelen);
if(!message) { if(!message) {
free(trailer); free(trailer);
Curl_unicodefree(user_name); curlx_unicodefree(user_name);
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
@ -421,7 +421,7 @@ CURLcode Curl_auth_create_gssapi_security_message(struct Curl_easy *data,
outdata = htonl(max_size) | sec_layer; outdata = htonl(max_size) | sec_layer;
memcpy(message, &outdata, sizeof(outdata)); memcpy(message, &outdata, sizeof(outdata));
strcpy((char *) message + sizeof(outdata), user_name); strcpy((char *) message + sizeof(outdata), user_name);
Curl_unicodefree(user_name); curlx_unicodefree(user_name);
/* Allocate the padding */ /* Allocate the padding */
padding = malloc(sizes.cbBlockSize); padding = malloc(sizes.cbBlockSize);

View File

@ -89,7 +89,7 @@ TCHAR *Curl_auth_build_spn(const char *service, const char *host,
} }
/* Allocate our TCHAR based SPN */ /* Allocate our TCHAR based SPN */
tchar_spn = Curl_convert_UTF8_to_tchar(utf8_spn); tchar_spn = curlx_convert_UTF8_to_tchar(utf8_spn);
if(!tchar_spn) { if(!tchar_spn) {
free(utf8_spn); free(utf8_spn);
@ -97,7 +97,7 @@ TCHAR *Curl_auth_build_spn(const char *service, const char *host,
} }
/* Release the UTF8 variant when operating with Unicode */ /* Release the UTF8 variant when operating with Unicode */
Curl_unicodefree(utf8_spn); curlx_unicodefree(utf8_spn);
/* Return our newly allocated SPN */ /* Return our newly allocated SPN */
return tchar_spn; return tchar_spn;

View File

@ -592,7 +592,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
HCERTSTORE cert_store; HCERTSTORE cert_store;
FILE *fInCert = NULL; FILE *fInCert = NULL;
TCHAR *cert_path = Curl_convert_UTF8_to_tchar(data->set.ssl.cert); TCHAR *cert_path = curlx_convert_UTF8_to_tchar(data->set.ssl.cert);
if(!cert_path) if(!cert_path)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
@ -605,7 +605,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
failf(data, "schannel: Failed to get certificate location" failf(data, "schannel: Failed to get certificate location"
" or file for %s", " or file for %s",
data->set.ssl.cert); data->set.ssl.cert);
Curl_unicodefree(cert_path); curlx_unicodefree(cert_path);
return result; return result;
} }
@ -633,7 +633,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
((int) fread(certdata, (size_t)filesize, 1, fInCert) != 1)) ((int) fread(certdata, (size_t)filesize, 1, fInCert) != 1))
continue_reading = 0; continue_reading = 0;
fclose(fInCert); fclose(fInCert);
Curl_unicodefree(cert_path); curlx_unicodefree(cert_path);
if(!continue_reading) { if(!continue_reading) {
failf(data, "schannel: Failed to read cert file %s", failf(data, "schannel: Failed to read cert file %s",
@ -700,7 +700,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
"last error is 0x%x", "last error is 0x%x",
cert_store_name, cert_store_path, GetLastError()); cert_store_name, cert_store_path, GetLastError());
free(cert_store_path); free(cert_store_path);
Curl_unicodefree(cert_path); curlx_unicodefree(cert_path);
return CURLE_SSL_CERTPROBLEM; return CURLE_SSL_CERTPROBLEM;
} }
free(cert_store_path); free(cert_store_path);
@ -714,7 +714,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
cert_thumbprint_data, cert_thumbprint_data,
&cert_thumbprint.cbData, &cert_thumbprint.cbData,
NULL, NULL)) { NULL, NULL)) {
Curl_unicodefree(cert_path); curlx_unicodefree(cert_path);
CertCloseStore(cert_store, 0); CertCloseStore(cert_store, 0);
return CURLE_SSL_CERTPROBLEM; return CURLE_SSL_CERTPROBLEM;
} }
@ -723,7 +723,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, cert_store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0,
CERT_FIND_HASH, &cert_thumbprint, NULL); CERT_FIND_HASH, &cert_thumbprint, NULL);
Curl_unicodefree(cert_path); curlx_unicodefree(cert_path);
if(client_certs[0]) { if(client_certs[0]) {
schannel_cred.cCreds = 1; schannel_cred.cCreds = 1;
@ -867,7 +867,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
host_name = Curl_convert_UTF8_to_tchar(hostname); host_name = curlx_convert_UTF8_to_tchar(hostname);
if(!host_name) if(!host_name)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
@ -884,7 +884,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
0, &BACKEND->ctxt->ctxt_handle, 0, &BACKEND->ctxt->ctxt_handle,
&outbuf_desc, &BACKEND->ret_flags, &BACKEND->ctxt->time_stamp); &outbuf_desc, &BACKEND->ret_flags, &BACKEND->ctxt->time_stamp);
Curl_unicodefree(host_name); curlx_unicodefree(host_name);
if(sspi_status != SEC_I_CONTINUE_NEEDED) { if(sspi_status != SEC_I_CONTINUE_NEEDED) {
char buffer[STRERROR_LEN]; char buffer[STRERROR_LEN];
@ -1067,7 +1067,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
memcpy(inbuf[0].pvBuffer, BACKEND->encdata_buffer, memcpy(inbuf[0].pvBuffer, BACKEND->encdata_buffer,
BACKEND->encdata_offset); BACKEND->encdata_offset);
host_name = Curl_convert_UTF8_to_tchar(hostname); host_name = curlx_convert_UTF8_to_tchar(hostname);
if(!host_name) if(!host_name)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
@ -1078,7 +1078,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
host_name, BACKEND->req_flags, 0, 0, &inbuf_desc, 0, NULL, host_name, BACKEND->req_flags, 0, 0, &inbuf_desc, 0, NULL,
&outbuf_desc, &BACKEND->ret_flags, &BACKEND->ctxt->time_stamp); &outbuf_desc, &BACKEND->ret_flags, &BACKEND->ctxt->time_stamp);
Curl_unicodefree(host_name); curlx_unicodefree(host_name);
/* free buffer for received handshake data */ /* free buffer for received handshake data */
Curl_safefree(inbuf[0].pvBuffer); Curl_safefree(inbuf[0].pvBuffer);
@ -2112,7 +2112,7 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer))); Curl_sspi_strerror(sspi_status, buffer, sizeof(buffer)));
} }
host_name = Curl_convert_UTF8_to_tchar(hostname); host_name = curlx_convert_UTF8_to_tchar(hostname);
if(!host_name) if(!host_name)
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
@ -2134,7 +2134,7 @@ static int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
&BACKEND->ret_flags, &BACKEND->ret_flags,
&BACKEND->ctxt->time_stamp); &BACKEND->ctxt->time_stamp);
Curl_unicodefree(host_name); curlx_unicodefree(host_name);
if((sspi_status == SEC_E_OK) || (sspi_status == SEC_I_CONTEXT_EXPIRED)) { if((sspi_status == SEC_E_OK) || (sspi_status == SEC_I_CONTEXT_EXPIRED)) {
/* send close message which is in output buffer */ /* send close message which is in output buffer */

View File

@ -94,7 +94,7 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store,
int num_certs = 0; int num_certs = 0;
size_t END_CERT_LEN; size_t END_CERT_LEN;
ca_file_tstr = Curl_convert_UTF8_to_tchar((char *)ca_file); ca_file_tstr = curlx_convert_UTF8_to_tchar((char *)ca_file);
if(!ca_file_tstr) { if(!ca_file_tstr) {
char buffer[STRERROR_LEN]; char buffer[STRERROR_LEN];
failf(data, failf(data,
@ -288,7 +288,7 @@ cleanup:
CloseHandle(ca_file_handle); CloseHandle(ca_file_handle);
} }
Curl_safefree(ca_file_buffer); Curl_safefree(ca_file_buffer);
Curl_unicodefree(ca_file_tstr); curlx_unicodefree(ca_file_tstr);
return result; return result;
} }
@ -476,7 +476,7 @@ static CURLcode verify_host(struct Curl_easy *data,
* is acceptable since both values are assumed to use ASCII * is acceptable since both values are assumed to use ASCII
* (or some equivalent) encoding * (or some equivalent) encoding
*/ */
cert_hostname = Curl_convert_tchar_to_UTF8( cert_hostname = curlx_convert_tchar_to_UTF8(
&cert_hostname_buff[cert_hostname_buff_index]); &cert_hostname_buff[cert_hostname_buff_index]);
if(!cert_hostname) { if(!cert_hostname) {
result = CURLE_OUT_OF_MEMORY; result = CURLE_OUT_OF_MEMORY;
@ -508,7 +508,7 @@ static CURLcode verify_host(struct Curl_easy *data,
result = CURLE_PEER_FAILED_VERIFICATION; result = CURLE_PEER_FAILED_VERIFICATION;
} }
Curl_unicodefree(cert_hostname); curlx_unicodefree(cert_hostname);
} }
} }
@ -522,7 +522,7 @@ static CURLcode verify_host(struct Curl_easy *data,
failf(data, "schannel: server certificate name verification failed"); failf(data, "schannel: server certificate name verification failed");
cleanup: cleanup:
Curl_unicodefree(cert_hostname_buff); curlx_unicodefree(cert_hostname_buff);
return result; return result;
} }

View File

@ -285,6 +285,7 @@ rem
call :element %1 lib "nonblock.c" %3 call :element %1 lib "nonblock.c" %3
call :element %1 lib "warnless.c" %3 call :element %1 lib "warnless.c" %3
call :element %1 lib "curl_ctype.c" %3 call :element %1 lib "curl_ctype.c" %3
call :element %1 lib "curl_multibyte.c" %3
) else if "!var!" == "CURL_SRC_X_H_FILES" ( ) else if "!var!" == "CURL_SRC_X_H_FILES" (
call :element %1 lib "config-win32.h" %3 call :element %1 lib "config-win32.h" %3
call :element %1 lib "curl_setup.h" %3 call :element %1 lib "curl_setup.h" %3
@ -292,6 +293,7 @@ rem
call :element %1 lib "nonblock.h" %3 call :element %1 lib "nonblock.h" %3
call :element %1 lib "warnless.h" %3 call :element %1 lib "warnless.h" %3
call :element %1 lib "curl_ctype.h" %3 call :element %1 lib "curl_ctype.h" %3
call :element %1 lib "curl_multibyte.h" %3
) else if "!var!" == "CURL_LIB_C_FILES" ( ) else if "!var!" == "CURL_LIB_C_FILES" (
for /f "delims=" %%c in ('dir /b ..\lib\*.c') do call :element %1 lib "%%c" %3 for /f "delims=" %%c in ('dir /b ..\lib\*.c') do call :element %1 lib "%%c" %3
) else if "!var!" == "CURL_LIB_H_FILES" ( ) else if "!var!" == "CURL_LIB_H_FILES" (

View File

@ -34,14 +34,16 @@ CURLX_CFILES = \
../lib/strtoofft.c \ ../lib/strtoofft.c \
../lib/nonblock.c \ ../lib/nonblock.c \
../lib/warnless.c \ ../lib/warnless.c \
../lib/curl_ctype.c ../lib/curl_ctype.c \
../lib/curl_multibyte.c
CURLX_HFILES = \ CURLX_HFILES = \
../lib/curl_setup.h \ ../lib/curl_setup.h \
../lib/strtoofft.h \ ../lib/strtoofft.h \
../lib/nonblock.h \ ../lib/nonblock.h \
../lib/warnless.h \ ../lib/warnless.h \
../lib/curl_ctype.h ../lib/curl_ctype.h \
../lib/curl_multibyte.h
CURL_CFILES = \ CURL_CFILES = \
slist_wc.c \ slist_wc.c \

View File

@ -30,7 +30,8 @@ CURLX_SRCS = \
../../lib/warnless.c \ ../../lib/warnless.c \
../../lib/curl_ctype.c \ ../../lib/curl_ctype.c \
../../lib/dynbuf.c \ ../../lib/dynbuf.c \
../../lib/strdup.c ../../lib/strdup.c \
../../lib/curl_multibyte.c
CURLX_HDRS = \ CURLX_HDRS = \
../../lib/curlx.h \ ../../lib/curlx.h \
@ -39,7 +40,8 @@ CURLX_HDRS = \
../../lib/warnless.h \ ../../lib/warnless.h \
../../lib/curl_ctype.h \ ../../lib/curl_ctype.h \
../../lib/dynbuf.h \ ../../lib/dynbuf.h \
../../lib/strdup.h ../../lib/strdup.h \
../../lib/curl_multibyte.h
USEFUL = \ USEFUL = \
getpart.c \ getpart.c \

View File

@ -618,7 +618,8 @@ CURL_FROM_LIBCURL=$(CURL_DIROBJ)\tool_hugehelp.obj \
$(CURL_DIROBJ)\nonblock.obj \ $(CURL_DIROBJ)\nonblock.obj \
$(CURL_DIROBJ)\strtoofft.obj \ $(CURL_DIROBJ)\strtoofft.obj \
$(CURL_DIROBJ)\warnless.obj \ $(CURL_DIROBJ)\warnless.obj \
$(CURL_DIROBJ)\curl_ctype.obj $(CURL_DIROBJ)\curl_ctype.obj \
$(CURL_DIROBJ)\curl_multibyte.obj
$(PROGRAM_NAME): $(CURL_DIROBJ) $(CURL_FROM_LIBCURL) $(EXE_OBJS) $(PROGRAM_NAME): $(CURL_DIROBJ) $(CURL_FROM_LIBCURL) $(EXE_OBJS)
$(CURL_LINK) $(CURL_LFLAGS) $(CURL_LIBCURL_LIBNAME) $(WIN_LIBS) $(CURL_FROM_LIBCURL) $(EXE_OBJS) $(CURL_LINK) $(CURL_LFLAGS) $(CURL_LIBCURL_LIBNAME) $(WIN_LIBS) $(CURL_FROM_LIBCURL) $(EXE_OBJS)
@ -637,6 +638,8 @@ $(CURL_DIROBJ)\warnless.obj: ../lib/warnless.c
$(CURL_CC) $(CURL_CFLAGS) /Fo"$@" ../lib/warnless.c $(CURL_CC) $(CURL_CFLAGS) /Fo"$@" ../lib/warnless.c
$(CURL_DIROBJ)\curl_ctype.obj: ../lib/curl_ctype.c $(CURL_DIROBJ)\curl_ctype.obj: ../lib/curl_ctype.c
$(CURL_CC) $(CURL_CFLAGS) /Fo"$@" ../lib/curl_ctype.c $(CURL_CC) $(CURL_CFLAGS) /Fo"$@" ../lib/curl_ctype.c
$(CURL_DIROBJ)\curl_multibyte.obj: ../lib/curl_multibyte.c
$(CURL_CC) $(CURL_CFLAGS) /Fo"$@" ../lib/curl_multibyte.c
$(CURL_DIROBJ)\curl.res: $(CURL_SRC_DIR)\curl.rc $(CURL_DIROBJ)\curl.res: $(CURL_SRC_DIR)\curl.rc
rc $(CURL_RC_FLAGS) rc $(CURL_RC_FLAGS)