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 | 42 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+)
diff --git a/dlls/ucrtbase/tests/file.c b/dlls/ucrtbase/tests/file.c index 5246a3723d9..2f4e1229f7f 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,47 @@ 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) + { + 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 2f4e1229f7f..1a1b1cc5832 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;
@@ -449,14 +450,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/process.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/msvcrt/process.c b/dlls/msvcrt/process.c index 5b16178b335..3b936321506 100644 --- a/dlls/msvcrt/process.c +++ b/dlls/msvcrt/process.c @@ -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 += convert_acp_utf8_to_wcs(*a, NULL, 0); a++; }
@@ -261,7 +261,7 @@ 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 += convert_acp_utf8_to_wcs(*a, p, len - (p - ret)); *p++ = delim; a++; } @@ -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, ' ');
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 3b936321506..9206eedb21d 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, ' '); envs = msvcrt_argvtos_aw(envv, 0); @@ -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, ' '); envs = msvcrt_argvtos_aw(envv, 0); @@ -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 | 13 +++++- dlls/ucrtbase/tests/file.c | 73 +++++++++------------------------- 3 files changed, 36 insertions(+), 64 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 39349345de0..2c17fc43a56 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,12 +415,20 @@ extern char* __cdecl __unDName(char *,const char*,int,malloc_func_t,free_func_t,
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); + UINT cp = CP_ACP; +#if _MSVCR_VER>=140 + if (___lc_codepage_func() == CP_UTF8) cp = CP_UTF8; +#endif + return MultiByteToWideChar(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); + UINT cp = CP_ACP; +#if _MSVCR_VER>=140 + if (___lc_codepage_func() == CP_UTF8) cp = CP_UTF8; +#endif + return WideCharToMultiByte(cp, 0, wstr, -1, str, len, NULL, NULL); }
static inline wchar_t* wstrdupa_utf8(const char *str) diff --git a/dlls/ucrtbase/tests/file.c b/dlls/ucrtbase/tests/file.c index 1a1b1cc5832..e48958455f2 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); @@ -464,8 +430,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=150257
Your paranoid android.
=== w1064v1809 (32 bit report) ===
ucrtbase: file.c:387: Test failed: environment variable name was converted
=== w1064v1809 (64 bit report) ===
ucrtbase: file.c:387: Test failed: environment variable name was converted
=== debian11 (32 bit report) ===
msvcrt: file.c:1771: Test failed: _spawnvp returned 1, errno 2 file.c:1772: Test failed: bad position 0 expecting 8 file.c:1774: Test failed: Couldn't read back the data file.c:1785: Test failed: _spawnvp returned 1, errno 2 file.c:1802: Test failed: _spawnvp returned 1, errno 2 file.c:1804: Test failed: bad position 0 expecting 8 file.c:1806: Test failed: Couldn't read back the data file.c:2530: Test failed: i 0, got 0 file.c:2533: Test failed: expected to read 'Hello world', got '' file.c:2530: Test failed: i 1, got 0 file.c:2533: Test failed: expected to read 'Hello world', got '' file.c:2530: Test failed: i 2, got 0 file.c:2533: Test failed: expected to read 'Hello world', got '' file.c:2566: Test failed: fread() returned 0: ferror=0 file.c:2569: Test failed: got '' expected 'Hello worldHello worldHello world'
=== debian11b (64 bit WoW report) ===
msvcrt: file.c:1771: Test failed: _spawnvp returned 1, errno 2 file.c:1772: Test failed: bad position 0 expecting 8 file.c:1774: Test failed: Couldn't read back the data file.c:1785: Test failed: _spawnvp returned 1, errno 2 file.c:1802: Test failed: _spawnvp returned 1, errno 2 file.c:1804: Test failed: bad position 0 expecting 8 file.c:1806: Test failed: Couldn't read back the data file.c:2530: Test failed: i 0, got 0 file.c:2533: Test failed: expected to read 'Hello world', got '' file.c:2530: Test failed: i 1, got 0 file.c:2533: Test failed: expected to read 'Hello world', got '' file.c:2530: Test failed: i 2, got 0 file.c:2533: Test failed: expected to read 'Hello world', got '' file.c:2566: Test failed: fread() returned 0: ferror=0 file.c:2569: Test failed: got '' expected 'Hello worldHello worldHello world'