-- v3: ucrtbase: Enable utf8 support. msvcrt: Prepare remaining process creation functions to handle utf-8 encoded arguments. msvcrt: Prepare _execle to handle utf-8 encoded arguments. msvcrt: Prepare _spawnl to handle utf-8 encoded arguments. msvcrt: Prepare _loaddll to handle utf-8 encoded path. msvcrt: Prepare freopen to handle utf-8 encoded path. msvcrt: Prepare _sopen_dispatch to handle utf-8 encoded path. msvcrt: Return error on NULL path parameter in _wsopen_dispatch. msvcrt: Add putenv() utf-8 tests.
From: Piotr Caban piotr@codeweavers.com
--- dlls/msvcrt/dir.c | 47 ++++++++++++++++++++++---------------- dlls/ucrtbase/tests/file.c | 11 +++++++++ 2 files changed, 38 insertions(+), 20 deletions(-)
diff --git a/dlls/msvcrt/dir.c b/dlls/msvcrt/dir.c index b72682db806..8e4549ab306 100644 --- a/dlls/msvcrt/dir.c +++ b/dlls/msvcrt/dir.c @@ -486,45 +486,52 @@ intptr_t CDECL _findfirst64(const char *fspec, struct _finddata64_t *ft) }
/********************************************************************* - * _findfirst64i32 (MSVCRT.@) + * _wfindfirst64i32 (MSVCRT.@) * - * 64-bit/32-bit version of _findfirst. + * Unicode version of _findfirst64i32. */ -intptr_t CDECL _findfirst64i32(const char * fspec, struct _finddata64i32_t* ft) +intptr_t CDECL _wfindfirst64i32(const wchar_t * fspec, struct _wfinddata64i32_t* ft) { - WIN32_FIND_DATAA find_data; + WIN32_FIND_DATAW find_data; HANDLE hfind;
- hfind = FindFirstFileA(fspec, &find_data); + hfind = FindFirstFileW(fspec, &find_data); if (hfind == INVALID_HANDLE_VALUE) { msvcrt_set_errno(GetLastError()); return -1; } - msvcrt_fttofd64i32(&find_data,ft); + msvcrt_wfttofd64i32(&find_data,ft); TRACE(":got handle %p\n",hfind); return (intptr_t)hfind; }
+static int finddata64i32_wtoa(const struct _wfinddata64i32_t *wfd, struct _finddata64i32_t *fd) +{ + fd->attrib = wfd->attrib; + fd->time_create = wfd->time_create; + fd->time_access = wfd->time_access; + fd->time_write = wfd->time_write; + fd->size = wfd->size; + return convert_wcs_to_acp_utf8(wfd->name, fd->name, ARRAY_SIZE(fd->name)); +} + /********************************************************************* - * _wfindfirst64i32 (MSVCRT.@) + * _findfirst64i32 (MSVCRT.@) * - * Unicode version of _findfirst64i32. + * 64-bit/32-bit version of _findfirst. */ -intptr_t CDECL _wfindfirst64i32(const wchar_t * fspec, struct _wfinddata64i32_t* ft) +intptr_t CDECL _findfirst64i32(const char *fspec, struct _finddata64i32_t *ft) { - WIN32_FIND_DATAW find_data; - HANDLE hfind; + struct _wfinddata64i32_t wft; + wchar_t *fspecW = NULL; + intptr_t ret;
- hfind = FindFirstFileW(fspec, &find_data); - if (hfind == INVALID_HANDLE_VALUE) - { - msvcrt_set_errno(GetLastError()); - return -1; - } - msvcrt_wfttofd64i32(&find_data,ft); - TRACE(":got handle %p\n",hfind); - return (intptr_t)hfind; + if (fspec && !(fspecW = wstrdupa_utf8(fspec))) return -1; + ret = _wfindfirst64i32(fspecW, &wft); + free(fspecW); + if (!finddata64i32_wtoa(&wft, ft)) return -1; + return ret; }
/********************************************************************* diff --git a/dlls/ucrtbase/tests/file.c b/dlls/ucrtbase/tests/file.c index ef732479165..7b7604480bf 100644 --- a/dlls/ucrtbase/tests/file.c +++ b/dlls/ucrtbase/tests/file.c @@ -239,6 +239,7 @@ static void test_utf8(void) const WCHAR dirW[] = L"dir\x0119\x015b\x0107";
char file2[32], buf[256], *p, *q; + struct _finddata64i32_t fdata64i32; struct _finddata32_t fdata32; struct _finddata64_t fdata64; struct _stat64 stat; @@ -353,6 +354,16 @@ static void test_utf8(void) ret = _findclose(hfind); ok(!ret, "_findclose returned %d, errno %d\n", ret, errno);
+ strcpy(buf, file); + strcat(buf, "*"); + fdata64i32.name[0] = 'x'; + hfind = _findfirst64i32(buf, &fdata64i32); + ok(hfind != -1, "_findfirst64i32 returned %Id, errno %d\n", hfind, errno); + todo_wine_if(!is_lossless_convertion(dir)) + ok(!memcmp(file, fdata64i32.name, sizeof(file) - 1), "fdata64i32.name = %s\n", debugstr_a(fdata64i32.name)); + ret = _findclose(hfind); + ok(!ret, "_findclose returned %d, errno %d\n", ret, errno); + ret = remove(file2); ok(!ret, "remove returned %d, errno %d\n", ret, errno);
From: Piotr Caban piotr@codeweavers.com
--- dlls/msvcrt/dir.c | 54 +++++++++++--------------------------- dlls/ucrtbase/tests/file.c | 6 +++++ 2 files changed, 21 insertions(+), 39 deletions(-)
diff --git a/dlls/msvcrt/dir.c b/dlls/msvcrt/dir.c index 8e4549ab306..7a36b74ee6b 100644 --- a/dlls/msvcrt/dir.c +++ b/dlls/msvcrt/dir.c @@ -157,26 +157,6 @@ static void msvcrt_wfttofd64( const WIN32_FIND_DATAW *fd, struct _wfinddata64_t* wcscpy(ft->name, fd->cFileName); }
-/* INTERNAL: Translate WIN32_FIND_DATAA to finddata64i32_t */ -static void msvcrt_fttofd64i32( const WIN32_FIND_DATAA *fd, struct _finddata64i32_t* ft) -{ - DWORD dw; - - if (fd->dwFileAttributes == FILE_ATTRIBUTE_NORMAL) - ft->attrib = 0; - else - ft->attrib = fd->dwFileAttributes; - - RtlTimeToSecondsSince1970( (const LARGE_INTEGER *)&fd->ftCreationTime, &dw ); - ft->time_create = dw; - RtlTimeToSecondsSince1970( (const LARGE_INTEGER *)&fd->ftLastAccessTime, &dw ); - ft->time_access = dw; - RtlTimeToSecondsSince1970( (const LARGE_INTEGER *)&fd->ftLastWriteTime, &dw ); - ft->time_write = dw; - ft->size = fd->nFileSizeLow; - strcpy(ft->name, fd->cFileName); -} - /* INTERNAL: Translate WIN32_FIND_DATAW to wfinddatai64_t */ static void msvcrt_wfttofdi64( const WIN32_FIND_DATAW *fd, struct _wfinddatai64_t* ft) { @@ -687,25 +667,6 @@ int CDECL _findnext64(intptr_t hand, struct _finddata64_t * ft) return ret; }
-/********************************************************************* - * _findnext64i32 (MSVCRT.@) - * - * 64-bit/32-bit version of _findnext. - */ -int CDECL _findnext64i32(intptr_t hand, struct _finddata64i32_t * ft) -{ - WIN32_FIND_DATAA find_data; - - if (!FindNextFileA((HANDLE)hand, &find_data)) - { - *_errno() = ENOENT; - return -1; - } - - msvcrt_fttofd64i32(&find_data,ft); - return 0; -} - /********************************************************************* * _wfindnexti64 (MSVCRT.@) * @@ -744,6 +705,21 @@ int CDECL _wfindnext64i32(intptr_t hand, struct _wfinddata64i32_t * ft) return 0; }
+/********************************************************************* + * _findnext64i32 (MSVCRT.@) + * + * 64-bit/32-bit version of _findnext. + */ +int CDECL _findnext64i32(intptr_t hand, struct _finddata64i32_t *ft) +{ + struct _wfinddata64i32_t wft; + int ret; + + ret = _wfindnext64i32(hand, &wft); + if (!ret && !finddata64i32_wtoa(&wft, ft)) ret = -1; + return ret; +} + /********************************************************************* * _getcwd (MSVCRT.@) * diff --git a/dlls/ucrtbase/tests/file.c b/dlls/ucrtbase/tests/file.c index 7b7604480bf..5246a3723d9 100644 --- a/dlls/ucrtbase/tests/file.c +++ b/dlls/ucrtbase/tests/file.c @@ -359,6 +359,12 @@ static void test_utf8(void) fdata64i32.name[0] = 'x'; hfind = _findfirst64i32(buf, &fdata64i32); ok(hfind != -1, "_findfirst64i32 returned %Id, errno %d\n", hfind, errno); + todo_wine_if(!is_lossless_convertion(dir)) + ok(!memcmp(file, fdata64i32.name, sizeof(file) - 1), "fdata64i32.name = %s\n", debugstr_a(fdata64i32.name)); + + fdata64i32.name[0] = 'x'; + ret = _findnext64i32(hfind, &fdata64i32); + ok(!ret, "_findnext64i32 returned %d, errno %d\n", ret, errno); todo_wine_if(!is_lossless_convertion(dir)) ok(!memcmp(file, fdata64i32.name, sizeof(file) - 1), "fdata64i32.name = %s\n", debugstr_a(fdata64i32.name)); ret = _findclose(hfind);
From: Piotr Caban piotr@codeweavers.com
The test shows that native has partial support for utf-8 that is currently broken. --- dlls/ucrtbase/tests/file.c | 47 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+)
diff --git a/dlls/ucrtbase/tests/file.c b/dlls/ucrtbase/tests/file.c index 5246a3723d9..7cada553303 100644 --- a/dlls/ucrtbase/tests/file.c +++ b/dlls/ucrtbase/tests/file.c @@ -242,6 +242,7 @@ static void test_utf8(void) struct _finddata64i32_t fdata64i32; struct _finddata32_t fdata32; struct _finddata64_t fdata64; + WCHAR bufW[256], *pW; struct _stat64 stat; intptr_t hfind; FILE *f; @@ -407,6 +408,52 @@ static void test_utf8(void) "incorrect file prefix: %s\n", debugstr_a(p)); free(p);
+ /* native implementation mixes CP_UTF8 and CP_ACP */ + if (GetACP() != CP_UTF8) + { + /* make sure wide environment is initialized (works around bug in native) */ + ret = _putenv("__wine_env_test=test"); + ok(!ret, "_putenv returned %d, errno %d\n", ret, errno); + _wgetenv(L"__wine_env_test"); + + strcpy(buf, file); + strcat(buf, "=test"); + ret = _putenv(buf); + ok(!ret, "_putenv returned %d, errno %d\n", ret, errno); + /* bug in native _wgetenv/_putenv implementation */ + pW = _wgetenv(fileW); + ok(!pW, "environment variable name was converted\n"); + bufW[0] = 0; + ret = GetEnvironmentVariableW(fileW, bufW, sizeof(bufW)); + todo_wine ok(ret, "GetEnvironmentVariableW returned error %lu\n", GetLastError()); + todo_wine ok(!wcscmp(bufW, L"test"), "bufW = %s\n", debugstr_w(bufW)); + strcpy(buf, file); + strcat(buf, "="); + ret = _putenv(buf); + ok(!ret, "_putenv returned %d, errno %d\n", ret, errno); + + strcpy(buf, "__wine_env_test="); + strcat(buf, file); + ret = _putenv(buf); + ok(!ret, "_putenv returned %d, errno %d\n", ret, errno); + /* bug in native _wgetenv/_putenv implementation */ + pW = _wgetenv(L"__wine_env_test"); + ok(wcscmp(pW, fileW), "pW = %s\n", debugstr_w(pW)); + ret = GetEnvironmentVariableW(L"__wine_env_test", bufW, sizeof(bufW)); + ok(ret, "GetEnvironmentVariableW returned error %lu\n", GetLastError()); + todo_wine ok(!wcscmp(bufW, fileW), "bufW = %s\n", debugstr_w(bufW)); + + wcscpy(bufW, L"__wine_env_test="); + wcscat(bufW, fileW); + ret = _wputenv(bufW); + ok(!ret, "_wputenv returned %d, errno %d\n", ret, errno); + p = getenv("__wine_env_test"); + ok(strcmp(p, file), "environment variable was converted\n"); + strcpy(buf, "__wine_env_test="); + ret = _putenv(buf); + ok(!ret, "_putenv returned %d, errno %d\n", ret, errno); + } + setlocale(LC_ALL, "C"); }
From: Piotr Caban piotr@codeweavers.com
--- dlls/msvcrt/file.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/dlls/msvcrt/file.c b/dlls/msvcrt/file.c index 22888d88a8a..bb1b0792ebe 100644 --- a/dlls/msvcrt/file.c +++ b/dlls/msvcrt/file.c @@ -2407,8 +2407,9 @@ int CDECL _wsopen_dispatch( const wchar_t* path, int oflags, int shflags, int pm debugstr_w(path), oflags, shflags, pmode, fd, secure);
if (!MSVCRT_CHECK_PMT( fd != NULL )) return EINVAL; - *fd = -1; + if (!MSVCRT_CHECK_PMT(path != NULL)) return EINVAL; + wxflag = split_oflags(oflags); switch (oflags & (_O_RDONLY | _O_WRONLY | _O_RDWR)) {
From: Piotr Caban piotr@codeweavers.com
--- dlls/msvcrt/file.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/dlls/msvcrt/file.c b/dlls/msvcrt/file.c index bb1b0792ebe..66ff2f5dcba 100644 --- a/dlls/msvcrt/file.c +++ b/dlls/msvcrt/file.c @@ -2606,14 +2606,13 @@ int WINAPIV _wsopen( const wchar_t *path, int oflags, int shflags, ... ) int CDECL _sopen_dispatch( const char *path, int oflags, int shflags, int pmode, int *fd, int secure) { - wchar_t *pathW; + wchar_t *pathW = NULL; int ret;
if (!MSVCRT_CHECK_PMT(fd != NULL)) return EINVAL; *fd = -1; - if(!MSVCRT_CHECK_PMT(path && (pathW = msvcrt_wstrdupa(path)))) - return EINVAL; + if (path && !(pathW = wstrdupa_utf8(path))) return *_errno();
ret = _wsopen_dispatch(pathW, oflags, shflags, pmode, fd, secure); free(pathW);
From: Piotr Caban piotr@codeweavers.com
--- dlls/msvcrt/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/msvcrt/file.c b/dlls/msvcrt/file.c index 66ff2f5dcba..dda12a70194 100644 --- a/dlls/msvcrt/file.c +++ b/dlls/msvcrt/file.c @@ -4626,7 +4626,7 @@ FILE* CDECL freopen(const char *path, const char *mode, FILE* file) FILE *ret; wchar_t *pathW = NULL, *modeW = NULL;
- if (path && !(pathW = msvcrt_wstrdupa(path))) return NULL; + if (path && !(pathW = wstrdupa_utf8(path))) return NULL; if (mode && !(modeW = msvcrt_wstrdupa(mode))) { free(pathW);
From: Piotr Caban piotr@codeweavers.com
--- dlls/msvcrt/process.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/dlls/msvcrt/process.c b/dlls/msvcrt/process.c index 630e378df87..625c3da84b9 100644 --- a/dlls/msvcrt/process.c +++ b/dlls/msvcrt/process.c @@ -1311,7 +1311,13 @@ int CDECL system(const char* cmd) */ intptr_t CDECL _loaddll(const char* dllname) { - return (intptr_t)LoadLibraryA(dllname); + wchar_t *dllnameW = NULL; + intptr_t ret; + + if (dllname && !(dllnameW = wstrdupa_utf8(dllname))) return 0; + ret = (intptr_t)LoadLibraryW(dllnameW); + free(dllnameW); + return ret; }
/*********************************************************************
From: Piotr Caban piotr@codeweavers.com
--- dlls/msvcrt/process.c | 6 +++--- dlls/ucrtbase/tests/file.c | 32 +++++++++++++++++++++++++++++--- 2 files changed, 32 insertions(+), 6 deletions(-)
diff --git a/dlls/msvcrt/process.c b/dlls/msvcrt/process.c index 625c3da84b9..5b16178b335 100644 --- a/dlls/msvcrt/process.c +++ b/dlls/msvcrt/process.c @@ -316,7 +316,7 @@ static wchar_t *msvcrt_valisttos_aw(const char *arg0, va_list alist, wchar_t del
for (arg = arg0; arg; arg = va_arg( alist, char * )) { - unsigned int len = MultiByteToWideChar( CP_ACP, 0, arg, -1, NULL, 0 ); + unsigned int len = convert_acp_utf8_to_wcs( arg, NULL, 0 ); if (pos + len >= size) { size = max( 256, size * 2 ); @@ -328,7 +328,7 @@ static wchar_t *msvcrt_valisttos_aw(const char *arg0, va_list alist, wchar_t del } ret = new; } - pos += MultiByteToWideChar( CP_ACP, 0, arg, -1, ret + pos, size - pos ); + pos += convert_acp_utf8_to_wcs( arg, ret + pos, size - pos ); ret[pos - 1] = delim; } if (pos) @@ -711,7 +711,7 @@ intptr_t WINAPIV _spawnl(int flags, const char* name, const char* arg0, ...) wchar_t *nameW, *args; intptr_t ret;
- if (!(nameW = msvcrt_wstrdupa(name))) return -1; + if (!(nameW = wstrdupa_utf8(name))) return -1;
va_start(ap, arg0); args = msvcrt_valisttos_aw(arg0, ap, ' '); diff --git a/dlls/ucrtbase/tests/file.c b/dlls/ucrtbase/tests/file.c index 7cada553303..ad64d1ea081 100644 --- a/dlls/ucrtbase/tests/file.c +++ b/dlls/ucrtbase/tests/file.c @@ -22,6 +22,7 @@ #include <direct.h> #include <stdarg.h> #include <locale.h> +#include <process.h> #include <share.h> #include <sys/stat.h>
@@ -231,7 +232,7 @@ static BOOL is_lossless_convertion(const char *str) return !strcmp(str, buf); }
-static void test_utf8(void) +static void test_utf8(const char *argv0) { const char file[] = "file\xc4\x99\xc5\x9b\xc4\x87.a"; const char dir[] = "dir\xc4\x99\xc5\x9b\xc4\x87"; @@ -242,9 +243,9 @@ static void test_utf8(void) struct _finddata64i32_t fdata64i32; struct _finddata32_t fdata32; struct _finddata64_t fdata64; + intptr_t hfind, hproc; WCHAR bufW[256], *pW; struct _stat64 stat; - intptr_t hfind; FILE *f; int ret;
@@ -454,14 +455,39 @@ static void test_utf8(void) ok(!ret, "_putenv returned %d, errno %d\n", ret, errno); }
+ hproc = _spawnl(_P_NOWAIT, argv0, argv0, "file", "utf8", file, NULL); + ok(hproc != -1, "_spawnl returned %Id, errno %d\n", hproc, errno); + wait_child_process((HANDLE)hproc); + CloseHandle((HANDLE)hproc); + setlocale(LC_ALL, "C"); }
+static void test_utf8_argument(void) +{ + const WCHAR *cmdline = GetCommandLineW(), *p; + + p = wcsrchr(cmdline, ' '); + ok(!!p, "cmdline = %s\n", debugstr_w(cmdline)); + todo_wine_if(GetACP() != CP_UTF8) + ok(!wcscmp(p + 1, L"file\x0119\x015b\x0107.a"), "cmdline = %s\n", debugstr_w(cmdline)); +} + START_TEST(file) { + int arg_c; + char** arg_v; + + arg_c = winetest_get_mainargs(&arg_v); + if(arg_c == 4 && !strcmp(arg_v[2], "utf8")) + { + test_utf8_argument(); + return; + } + test_std_stream_buffering(); test_iobuf_layout(); test_std_stream_open(); test_fopen(); - test_utf8(); + test_utf8(arg_v[0]); }
From: Piotr Caban piotr@codeweavers.com
--- dlls/msvcrt/msvcrt.h | 9 +++++++-- dlls/msvcrt/process.c | 32 ++++++++++++++++---------------- 2 files changed, 23 insertions(+), 18 deletions(-)
diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h index 39349345de0..8072d5117df 100644 --- a/dlls/msvcrt/msvcrt.h +++ b/dlls/msvcrt/msvcrt.h @@ -412,14 +412,19 @@ extern char* __cdecl __unDName(char *,const char*,int,malloc_func_t,free_func_t,
#define INHERIT_THREAD_PRIORITY 0xF000
+static inline UINT get_aw_cp(void) +{ + return CP_ACP; +} + static inline int convert_acp_utf8_to_wcs(const char *str, wchar_t *wstr, int len) { - return MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, str, -1, wstr, len); + return MultiByteToWideChar(get_aw_cp(), MB_PRECOMPOSED, str, -1, wstr, len); }
static inline int convert_wcs_to_acp_utf8(const wchar_t *wstr, char *str, int len) { - return WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, len, NULL, NULL); + return WideCharToMultiByte(get_aw_cp(), 0, wstr, -1, str, len, NULL, NULL); }
static inline wchar_t* wstrdupa_utf8(const char *str) diff --git a/dlls/msvcrt/process.c b/dlls/msvcrt/process.c index 5b16178b335..ed62ed871fd 100644 --- a/dlls/msvcrt/process.c +++ b/dlls/msvcrt/process.c @@ -228,10 +228,10 @@ static wchar_t* msvcrt_argvtos(const wchar_t* const* arg, wchar_t delim) return ret; }
-/* INTERNAL: Convert ansi argv list to a single 'delim'-separated wide string, with an - * extra '\0' to terminate it. +/* INTERNAL: Convert ansi argv list to a single wide string, use ' ' or '\0' + * as separator depending on env argument. */ -static wchar_t *msvcrt_argvtos_aw(const char * const *arg, wchar_t delim) +static wchar_t *msvcrt_argvtos_aw(const char * const *arg, BOOL env) { const char * const *a; unsigned int len; @@ -248,7 +248,7 @@ static wchar_t *msvcrt_argvtos_aw(const char * const *arg, wchar_t delim) len = 0; while (*a) { - len += MultiByteToWideChar(CP_ACP, 0, *a, -1, NULL, 0); + len += MultiByteToWideChar(get_aw_cp(), 0, *a, -1, NULL, 0); a++; }
@@ -261,11 +261,11 @@ static wchar_t *msvcrt_argvtos_aw(const char * const *arg, wchar_t delim) p = ret; while (*a) { - p += MultiByteToWideChar(CP_ACP, 0, *a, strlen(*a), p, len - (p - ret)); - *p++ = delim; + p += MultiByteToWideChar(get_aw_cp(), 0, *a, strlen(*a), p, len - (p - ret)); + *p++ = env ? 0 : ' '; a++; } - if (delim && p > ret) p[-1] = 0; + if (!env && p > ret) p[-1] = 0; else *p = 0; return ret; } @@ -469,7 +469,7 @@ intptr_t WINAPIV _execle(const char* name, const char* arg0, ...) const char * const *envp; intptr_t ret;
- if (!(nameW = msvcrt_wstrdupa(name))) return -1; + if (!(nameW = wstrdupa_utf8(name))) return -1;
va_start(ap, arg0); args = msvcrt_valisttos_aw(arg0, ap, ' '); @@ -478,7 +478,7 @@ intptr_t WINAPIV _execle(const char* name, const char* arg0, ...) va_start(ap, arg0); while (va_arg( ap, char * ) != NULL) /*nothing*/; envp = va_arg( ap, const char * const * ); - if (envp) envs = msvcrt_argvtos_aw(envp, 0); + if (envp) envs = msvcrt_argvtos_aw(envp, TRUE); va_end(ap);
ret = msvcrt_spawn(_P_OVERLAY, nameW, args, envs, 0); @@ -583,7 +583,7 @@ intptr_t WINAPIV _execlpe(const char* name, const char* arg0, ...) va_start(ap, arg0); while (va_arg( ap, char * ) != NULL) /*nothing*/; envp = va_arg( ap, const char * const * ); - if (envp) envs = msvcrt_argvtos_aw(envp, 0); + if (envp) envs = msvcrt_argvtos_aw(envp, TRUE); va_end(ap);
ret = msvcrt_spawn(_P_OVERLAY, nameW, args, envs, 1); @@ -772,7 +772,7 @@ intptr_t WINAPIV _spawnle(int flags, const char* name, const char* arg0, ...) va_start(ap, arg0); while (va_arg( ap, char * ) != NULL) /*nothing*/; envp = va_arg( ap, const char * const * ); - if (envp) envs = msvcrt_argvtos_aw(envp, 0); + if (envp) envs = msvcrt_argvtos_aw(envp, TRUE); va_end(ap);
ret = msvcrt_spawn(flags, nameW, args, envs, 0); @@ -877,7 +877,7 @@ intptr_t WINAPIV _spawnlpe(int flags, const char* name, const char* arg0, ...) va_start(ap, arg0); while (va_arg( ap, char * ) != NULL) /*nothing*/; envp = va_arg( ap, const char * const * ); - if (envp) envs = msvcrt_argvtos_aw(envp, 0); + if (envp) envs = msvcrt_argvtos_aw(envp, TRUE); va_end(ap);
ret = msvcrt_spawn(flags, nameW, args, envs, 1); @@ -902,8 +902,8 @@ intptr_t CDECL _spawnve(int flags, const char* name, const char* const* argv,
if (!(nameW = msvcrt_wstrdupa(name))) return -1;
- args = msvcrt_argvtos_aw(argv, ' '); - envs = msvcrt_argvtos_aw(envv, 0); + args = msvcrt_argvtos_aw(argv, FALSE); + envs = msvcrt_argvtos_aw(envv, TRUE);
ret = msvcrt_spawn(flags, nameW, args, envs, 0);
@@ -969,8 +969,8 @@ intptr_t CDECL _spawnvpe(int flags, const char* name, const char* const* argv,
if (!(nameW = msvcrt_wstrdupa(name))) return -1;
- args = msvcrt_argvtos_aw(argv, ' '); - envs = msvcrt_argvtos_aw(envv, 0); + args = msvcrt_argvtos_aw(argv, FALSE); + envs = msvcrt_argvtos_aw(envv, TRUE);
ret = msvcrt_spawn(flags, nameW, args, envs, 1);
From: Piotr Caban piotr@codeweavers.com
--- dlls/msvcrt/process.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/dlls/msvcrt/process.c b/dlls/msvcrt/process.c index ed62ed871fd..c6e172ba42c 100644 --- a/dlls/msvcrt/process.c +++ b/dlls/msvcrt/process.c @@ -417,7 +417,7 @@ intptr_t WINAPIV _execl(const char* name, const char* arg0, ...) wchar_t *nameW, *args; intptr_t ret;
- if (!(nameW = msvcrt_wstrdupa(name))) return -1; + if (!(nameW = wstrdupa_utf8(name))) return -1;
va_start(ap, arg0); args = msvcrt_valisttos_aw(arg0, ap, ' '); @@ -522,7 +522,7 @@ intptr_t WINAPIV _execlp(const char* name, const char* arg0, ...) wchar_t *nameW, *args; intptr_t ret;
- if (!(nameW = msvcrt_wstrdupa(name))) return -1; + if (!(nameW = wstrdupa_utf8(name))) return -1;
va_start(ap, arg0); args = msvcrt_valisttos_aw(arg0, ap, ' '); @@ -574,7 +574,7 @@ intptr_t WINAPIV _execlpe(const char* name, const char* arg0, ...) const char * const *envp; intptr_t ret;
- if (!(nameW = msvcrt_wstrdupa(name))) return -1; + if (!(nameW = wstrdupa_utf8(name))) return -1;
va_start(ap, arg0); args = msvcrt_valisttos_aw(arg0, ap, ' '); @@ -763,7 +763,7 @@ intptr_t WINAPIV _spawnle(int flags, const char* name, const char* arg0, ...) const char * const *envp; intptr_t ret;
- if (!(nameW = msvcrt_wstrdupa(name))) return -1; + if (!(nameW = wstrdupa_utf8(name))) return -1;
va_start(ap, arg0); args = msvcrt_valisttos_aw(arg0, ap, ' '); @@ -816,7 +816,7 @@ intptr_t WINAPIV _spawnlp(int flags, const char* name, const char* arg0, ...) wchar_t *nameW, *args; intptr_t ret;
- if (!(nameW = msvcrt_wstrdupa(name))) return -1; + if (!(nameW = wstrdupa_utf8(name))) return -1;
va_start(ap, arg0); args = msvcrt_valisttos_aw(arg0, ap, ' '); @@ -868,7 +868,7 @@ intptr_t WINAPIV _spawnlpe(int flags, const char* name, const char* arg0, ...) const char * const *envp; intptr_t ret;
- if (!(nameW = msvcrt_wstrdupa(name))) return -1; + if (!(nameW = wstrdupa_utf8(name))) return -1;
va_start(ap, arg0); args = msvcrt_valisttos_aw(arg0, ap, ' '); @@ -900,7 +900,7 @@ intptr_t CDECL _spawnve(int flags, const char* name, const char* const* argv, wchar_t *nameW, *args, *envs; intptr_t ret;
- if (!(nameW = msvcrt_wstrdupa(name))) return -1; + if (!(nameW = wstrdupa_utf8(name))) return -1;
args = msvcrt_argvtos_aw(argv, FALSE); envs = msvcrt_argvtos_aw(envv, TRUE); @@ -967,7 +967,7 @@ intptr_t CDECL _spawnvpe(int flags, const char* name, const char* const* argv, wchar_t *nameW, *args, *envs; intptr_t ret;
- if (!(nameW = msvcrt_wstrdupa(name))) return -1; + if (!(nameW = wstrdupa_utf8(name))) return -1;
args = msvcrt_argvtos_aw(argv, FALSE); envs = msvcrt_argvtos_aw(envv, TRUE); @@ -1189,7 +1189,7 @@ FILE* CDECL _popen(const char* command, const char* mode) if (!command || !mode) return NULL;
- if (!(cmdW = msvcrt_wstrdupa(command))) return NULL; + if (!(cmdW = wstrdupa_utf8(command))) return NULL; if (!(modeW = msvcrt_wstrdupa(mode))) { free(cmdW); @@ -1298,7 +1298,7 @@ int CDECL system(const char* cmd) if (cmd == NULL) return _wsystem(NULL);
- if ((cmdW = msvcrt_wstrdupa(cmd))) + if ((cmdW = wstrdupa_utf8(cmd))) { res = _wsystem(cmdW); free(cmdW);
From: Piotr Caban piotr@codeweavers.com
--- dlls/msvcp140/tests/msvcp140.c | 14 +++---- dlls/msvcrt/msvcrt.h | 4 ++ dlls/ucrtbase/tests/file.c | 73 +++++++++------------------------- 3 files changed, 29 insertions(+), 62 deletions(-)
diff --git a/dlls/msvcp140/tests/msvcp140.c b/dlls/msvcp140/tests/msvcp140.c index 9c18afd76fc..128ea20add2 100644 --- a/dlls/msvcp140/tests/msvcp140.c +++ b/dlls/msvcp140/tests/msvcp140.c @@ -1709,14 +1709,13 @@ static void test__Fiopen(void) static const struct { const char *loc; const char *path; - int is_todo; } tests[] = { - { "German.utf8", "t\xc3\xa4\xc3\x8f\xc3\xb6\xc3\x9f.txt", TRUE }, - { "Polish.utf8", "t\xc4\x99\xc5\x9b\xc4\x87.txt", TRUE }, - { "Turkish.utf8", "t\xc3\x87\xc4\x9e\xc4\xb1\xc4\xb0\xc5\x9e.txt", TRUE }, - { "Arabic.utf8", "t\xd8\xaa\xda\x86.txt", TRUE }, - { "Japanese.utf8", "t\xe3\x82\xaf\xe3\x83\xa4.txt", TRUE }, - { "Chinese.utf8", "t\xe4\xb8\x82\xe9\xbd\xab.txt", TRUE }, + { "German.utf8", "t\xc3\xa4\xc3\x8f\xc3\xb6\xc3\x9f.txt" }, + { "Polish.utf8", "t\xc4\x99\xc5\x9b\xc4\x87.txt" }, + { "Turkish.utf8", "t\xc3\x87\xc4\x9e\xc4\xb1\xc4\xb0\xc5\x9e.txt" }, + { "Arabic.utf8", "t\xd8\xaa\xda\x86.txt" }, + { "Japanese.utf8", "t\xe3\x82\xaf\xe3\x83\xa4.txt" }, + { "Chinese.utf8", "t\xe4\xb8\x82\xe9\xbd\xab.txt" }, };
for(i=0; i<ARRAY_SIZE(tests); i++) { @@ -1734,7 +1733,6 @@ static void test__Fiopen(void) p_fclose(f);
f = p__Fiopen_wchar(wpath, OPENMODE_in, SH_DENYNO); - todo_wine_if(tests[i].is_todo && GetACP() != CP_UTF8) ok(!!f, "failed to open %s with locale %s\n", wine_dbgstr_w(wpath), tests[i].loc); if(f) p_fclose(f);
diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h index 8072d5117df..480d0e238fc 100644 --- a/dlls/msvcrt/msvcrt.h +++ b/dlls/msvcrt/msvcrt.h @@ -53,6 +53,7 @@ typedef struct _iobuf #endif
#include <errno.h> +#include <locale.h> #include <stdarg.h> #include <stdint.h> #define _NO_CRT_STDIO_INLINE @@ -414,6 +415,9 @@ extern char* __cdecl __unDName(char *,const char*,int,malloc_func_t,free_func_t,
static inline UINT get_aw_cp(void) { +#if _MSVCR_VER>=140 + if (___lc_codepage_func() == CP_UTF8) return CP_UTF8; +#endif return CP_ACP; }
diff --git a/dlls/ucrtbase/tests/file.c b/dlls/ucrtbase/tests/file.c index ad64d1ea081..de7415bb2fc 100644 --- a/dlls/ucrtbase/tests/file.c +++ b/dlls/ucrtbase/tests/file.c @@ -181,14 +181,13 @@ static void test_fopen(void) static const struct { const char *loc; const char *path; - int is_todo; } tests[] = { - { "German.utf8", "t\xc3\xa4\xc3\x8f\xc3\xb6\xc3\x9f.txt", TRUE }, - { "Polish.utf8", "t\xc4\x99\xc5\x9b\xc4\x87.txt", TRUE }, - { "Turkish.utf8", "t\xc3\x87\xc4\x9e\xc4\xb1\xc4\xb0\xc5\x9e.txt", TRUE }, - { "Arabic.utf8", "t\xd8\xaa\xda\x86.txt", TRUE }, - { "Japanese.utf8", "t\xe3\x82\xaf\xe3\x83\xa4.txt", TRUE }, - { "Chinese.utf8", "t\xe4\xb8\x82\xe9\xbd\xab.txt", TRUE }, + { "German.utf8", "t\xc3\xa4\xc3\x8f\xc3\xb6\xc3\x9f.txt" }, + { "Polish.utf8", "t\xc4\x99\xc5\x9b\xc4\x87.txt" }, + { "Turkish.utf8", "t\xc3\x87\xc4\x9e\xc4\xb1\xc4\xb0\xc5\x9e.txt" }, + { "Arabic.utf8", "t\xd8\xaa\xda\x86.txt" }, + { "Japanese.utf8", "t\xe3\x82\xaf\xe3\x83\xa4.txt" }, + { "Chinese.utf8", "t\xe4\xb8\x82\xe9\xbd\xab.txt" }, { "Japanese", "t\xb8\xd5.txt" },
}; @@ -209,7 +208,6 @@ static void test_fopen(void) fclose(f);
f = _wfsopen(wpath, L"r", SH_DENYNO); - todo_wine_if(tests[i].is_todo && GetACP() != CP_UTF8) ok(!!f, "failed to open %s with locale %s\n", debugstr_a(tests[i].path), tests[i].loc); if(f) fclose(f); @@ -220,18 +218,6 @@ static void test_fopen(void) setlocale(LC_ALL, "C"); }
-static BOOL is_lossless_convertion(const char *str) -{ - wchar_t bufW[32]; - char buf[32]; - - if (!MultiByteToWideChar(CP_ACP, 0, str, -1, bufW, ARRAY_SIZE(bufW))) - return FALSE; - if (!WideCharToMultiByte(CP_ACP, 0, bufW, -1, buf, ARRAY_SIZE(buf), NULL, NULL)) - return FALSE; - return !strcmp(str, buf); -} - static void test_utf8(const char *argv0) { const char file[] = "file\xc4\x99\xc5\x9b\xc4\x87.a"; @@ -270,22 +256,19 @@ static void test_utf8(const char *argv0) ok(p == buf, "_getcwd returned %p, errno %d\n", p, errno); p = strrchr(p, '\'); ok(!!p, "strrchr returned NULL, buf = %s\n", debugstr_a(buf)); - todo_wine_if(!is_lossless_convertion(dir)) - ok(!strcmp(p + 1, dir), "unexpected working directory: %s\n", debugstr_a(buf)); + ok(!strcmp(p + 1, dir), "unexpected working directory: %s\n", debugstr_a(buf));
p = _getdcwd(_getdrive(), buf, sizeof(buf)); ok(p == buf, "_getdcwd returned %p, errno %d\n", p, errno); p = strrchr(p, '\'); ok(!!p, "strrchr returned NULL, buf = %s\n", debugstr_a(buf)); - todo_wine_if(!is_lossless_convertion(dir)) - ok(!strcmp(p + 1, dir), "unexpected working directory: %s\n", debugstr_a(buf)); + ok(!strcmp(p + 1, dir), "unexpected working directory: %s\n", debugstr_a(buf));
p = _fullpath(buf, NULL, sizeof(buf)); ok(p == buf, "_fulpath returned %p, errno %d\n", p, errno); p = strrchr(p, '\'); ok(!!p, "strrchr returned NULL, buf = %s\n", debugstr_a(buf)); - todo_wine_if(!is_lossless_convertion(dir)) - ok(!strcmp(p + 1, dir), "unexpected working directory: %s\n", debugstr_a(buf)); + ok(!strcmp(p + 1, dir), "unexpected working directory: %s\n", debugstr_a(buf));
f = fopen(file, "w"); ok(!!f, "fopen returned %d, error %d\n", ret, errno); @@ -328,14 +311,12 @@ static void test_utf8(const char *argv0) fdata32.name[0] = 'x'; hfind = _findfirst32(buf, &fdata32); ok(hfind != -1, "_findfirst32 returned %Id, errno %d\n", hfind, errno); - todo_wine_if(!is_lossless_convertion(dir)) - ok(!memcmp(file, fdata32.name, sizeof(file) - 1), "fdata32.name = %s\n", debugstr_a(fdata32.name)); + ok(!memcmp(file, fdata32.name, sizeof(file) - 1), "fdata32.name = %s\n", debugstr_a(fdata32.name));
fdata32.name[0] = 'x'; ret = _findnext32(hfind, &fdata32); ok(!ret, "_findnext32 returned %d, errno %d\n", ret, errno); - todo_wine_if(!is_lossless_convertion(dir)) - ok(!memcmp(file, fdata32.name, sizeof(file) - 1), "fdata32.name = %s\n", debugstr_a(fdata32.name)); + ok(!memcmp(file, fdata32.name, sizeof(file) - 1), "fdata32.name = %s\n", debugstr_a(fdata32.name)); ret = _findclose(hfind); ok(!ret, "_findclose returned %d, errno %d\n", ret, errno);
@@ -345,14 +326,12 @@ static void test_utf8(const char *argv0) fdata64.name[0] = 'x'; hfind = _findfirst64(buf, &fdata64); ok(hfind != -1, "_findfirst64 returned %Id, errno %d\n", hfind, errno); - todo_wine_if(!is_lossless_convertion(dir)) - ok(!memcmp(file, fdata64.name, sizeof(file) - 1), "fdata64.name = %s\n", debugstr_a(fdata64.name)); + ok(!memcmp(file, fdata64.name, sizeof(file) - 1), "fdata64.name = %s\n", debugstr_a(fdata64.name));
fdata64.name[0] = 'x'; ret = _findnext64(hfind, &fdata64); ok(!ret, "_findnext64 returned %d, errno %d\n", ret, errno); - todo_wine_if(!is_lossless_convertion(dir)) - ok(!memcmp(file, fdata64.name, sizeof(file) - 1), "fdata64.name = %s\n", debugstr_a(fdata64.name)); + ok(!memcmp(file, fdata64.name, sizeof(file) - 1), "fdata64.name = %s\n", debugstr_a(fdata64.name)); ret = _findclose(hfind); ok(!ret, "_findclose returned %d, errno %d\n", ret, errno);
@@ -361,14 +340,12 @@ static void test_utf8(const char *argv0) fdata64i32.name[0] = 'x'; hfind = _findfirst64i32(buf, &fdata64i32); ok(hfind != -1, "_findfirst64i32 returned %Id, errno %d\n", hfind, errno); - todo_wine_if(!is_lossless_convertion(dir)) - ok(!memcmp(file, fdata64i32.name, sizeof(file) - 1), "fdata64i32.name = %s\n", debugstr_a(fdata64i32.name)); + ok(!memcmp(file, fdata64i32.name, sizeof(file) - 1), "fdata64i32.name = %s\n", debugstr_a(fdata64i32.name));
fdata64i32.name[0] = 'x'; ret = _findnext64i32(hfind, &fdata64i32); ok(!ret, "_findnext64i32 returned %d, errno %d\n", ret, errno); - todo_wine_if(!is_lossless_convertion(dir)) - ok(!memcmp(file, fdata64i32.name, sizeof(file) - 1), "fdata64i32.name = %s\n", debugstr_a(fdata64i32.name)); + ok(!memcmp(file, fdata64i32.name, sizeof(file) - 1), "fdata64i32.name = %s\n", debugstr_a(fdata64i32.name)); ret = _findclose(hfind); ok(!ret, "_findclose returned %d, errno %d\n", ret, errno);
@@ -379,27 +356,16 @@ static void test_utf8(const char *argv0) _searchenv(file, "env", buf); p = strrchr(buf, '\'); ok(!!p, "buf = %s\n", debugstr_a(buf)); - todo_wine_if(!is_lossless_convertion(file)) - ok(!strcmp(p + 1, file), "buf = %s\n", debugstr_a(buf)); + ok(!strcmp(p + 1, file), "buf = %s\n", debugstr_a(buf));
ret = _wunlink(fileW); - todo_wine_if(GetACP() != CP_UTF8) ok(!ret, "_wunlink returned %d, errno %d\n", ret, errno); - if (ret) - { - ret = _unlink(file); - ok(!ret, "_unlink returned %d, errno %d\n", ret, errno); - } + ok(!ret, "_wunlink returned %d, errno %d\n", ret, errno);
ret = _chdir(".."); ok(!ret, "_chdir returned %d, error %d\n", ret, errno);
ret = _wrmdir(dirW); - todo_wine_if(GetACP() != CP_UTF8) ok(!ret, "_wrmdir returned %d, errno %d\n", ret, errno); - if (ret) - { - ret = _rmdir(dir); - ok(!ret, "_rmdir returned %d, errno %d\n", ret, errno); - } + ok(!ret, "_wrmdir returned %d, errno %d\n", ret, errno);
p = _tempnam(NULL, file); ok(!!p, "_tempnam returned NULL, error %d\n", errno); @@ -469,8 +435,7 @@ static void test_utf8_argument(void)
p = wcsrchr(cmdline, ' '); ok(!!p, "cmdline = %s\n", debugstr_w(cmdline)); - todo_wine_if(GetACP() != CP_UTF8) - ok(!wcscmp(p + 1, L"file\x0119\x015b\x0107.a"), "cmdline = %s\n", debugstr_w(cmdline)); + ok(!wcscmp(p + 1, L"file\x0119\x015b\x0107.a"), "cmdline = %s\n", debugstr_w(cmdline)); }
START_TEST(file)
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=150264
Your paranoid android.
=== debian11b (64 bit WoW report) ===
user32: input.c:4305: Test succeeded inside todo block: button_down_hwnd_todo 1: got MSG_TEST_WIN hwnd 00000000009200D6, msg WM_LBUTTONDOWN, wparam 0x1, lparam 0x320032