-- v5: msvcp140: Call into fopen from _Fiopen. msvcp140/tests: Add tests for _Fiopen. ucrtbase/tests: Add tests for _fsopen. include: Add ___lc_codepage_func() declaration.
From: Piotr Caban piotr@codeweavers.com
--- dlls/msvcp90/locale.c | 1 - include/msvcrt/locale.h | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/dlls/msvcp90/locale.c b/dlls/msvcp90/locale.c index 6cbc91d5f5a..1f826ac485f 100644 --- a/dlls/msvcp90/locale.c +++ b/dlls/msvcp90/locale.c @@ -51,7 +51,6 @@ wchar_t* __cdecl _W_Getdays(void); char* __cdecl _Getmonths(void); wchar_t* __cdecl _W_Getmonths(void); void* __cdecl _Gettnames(void); -unsigned int __cdecl ___lc_codepage_func(void); int __cdecl ___lc_collate_cp_func(void); const locale_facet* __thiscall locale__Getfacet(const locale*, size_t); const locale* __cdecl locale_classic(void); diff --git a/include/msvcrt/locale.h b/include/msvcrt/locale.h index d2963813475..8186f1756fd 100644 --- a/include/msvcrt/locale.h +++ b/include/msvcrt/locale.h @@ -92,6 +92,8 @@ _ACRTIMP _locale_t __cdecl _get_current_locale(void); _ACRTIMP _locale_t __cdecl _create_locale(int, const char*); _ACRTIMP void __cdecl _free_locale(_locale_t);
+_ACRTIMP unsigned int __cdecl ___lc_codepage_func(void); + #ifndef _WLOCALE_DEFINED #define _WLOCALE_DEFINED _ACRTIMP wchar_t* __cdecl _wsetlocale(int,const wchar_t*);
From: Daniel Lehman dlehman25@gmail.com
--- dlls/ucrtbase/tests/file.c | 56 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+)
diff --git a/dlls/ucrtbase/tests/file.c b/dlls/ucrtbase/tests/file.c index 9bfb7af3384..5e384033540 100644 --- a/dlls/ucrtbase/tests/file.c +++ b/dlls/ucrtbase/tests/file.c @@ -18,6 +18,13 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#include <stdarg.h> +#include <locale.h> +#include <share.h> + +#include <windef.h> +#include <winbase.h> +#include <winnls.h> #include "wine/test.h"
static void test_std_stream_buffering(void) @@ -162,9 +169,58 @@ static void test_std_stream_open(void) close(fd); }
+static void test_fopen(void) +{ + int i; + FILE *f; + wchar_t wpath[MAX_PATH]; + 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 }, + { "Japanese", "t\xb8\xd5.txt" }, + + }; + + for(i=0; i<ARRAY_SIZE(tests); i++) { + if(!setlocale(LC_ALL, tests[i].loc)) { + win_skip("skipping locale %s\n", tests[i].loc); + continue; + } + + ok(MultiByteToWideChar(___lc_codepage_func() == CP_UTF8 ? CP_UTF8 : CP_ACP, + 0, tests[i].path, -1, wpath, MAX_PATH), + "MultiByteToWideChar failed on %s with locale %s: %lx\n", + debugstr_a(tests[i].path), tests[i].loc, GetLastError()); + + f = _fsopen(tests[i].path, "w", SH_DENYNO); + ok(!!f, "failed to create %s with locale %s\n", + debugstr_a(tests[i].path), tests[i].loc); + fclose(f); + + f = _wfsopen(wpath, L"r", SH_DENYNO); + todo_wine_if(tests[i].is_todo) + ok(!!f, "failed to open %s with locale %s\n", + debugstr_a(tests[i].path), tests[i].loc); + if(f) fclose(f); + + ok(!unlink(tests[i].path), "failed to unlink %s with locale %s\n", + tests[i].path, tests[i].loc); + } + setlocale(LC_ALL, "C"); +} + START_TEST(file) { test_std_stream_buffering(); test_iobuf_layout(); test_std_stream_open(); + test_fopen(); }
From: Daniel Lehman dlehman25@gmail.com
--- dlls/msvcp140/tests/msvcp140.c | 74 ++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+)
diff --git a/dlls/msvcp140/tests/msvcp140.c b/dlls/msvcp140/tests/msvcp140.c index faf4c214801..520a496e0bb 100644 --- a/dlls/msvcp140/tests/msvcp140.c +++ b/dlls/msvcp140/tests/msvcp140.c @@ -18,6 +18,8 @@
#include <errno.h> #include <stdio.h> +#include <locale.h> +#include <share.h>
#include "windef.h" #include "winbase.h" @@ -253,6 +255,24 @@ static ULONG (__cdecl *p__Winerror_message)(ULONG, char*, ULONG); static int (__cdecl *p__Winerror_map)(int); static const char* (__cdecl *p__Syserror_map)(int err);
+typedef enum { + OPENMODE_in = 0x01, + OPENMODE_out = 0x02, + OPENMODE_ate = 0x04, + OPENMODE_app = 0x08, + OPENMODE_trunc = 0x10, + OPENMODE__Nocreate = 0x40, + OPENMODE__Noreplace = 0x80, + OPENMODE_binary = 0x20, + OPENMODE_mask = 0xff +} IOSB_openmode; +static FILE* (__cdecl *p__Fiopen_wchar)(const wchar_t*, int, int); +static FILE* (__cdecl *p__Fiopen)(const char*, int, int); + +static char* (__cdecl *p_setlocale)(int, const char*); +static int (__cdecl *p_fclose)(FILE*); +static int (__cdecl *p__unlink)(const char*); + static BOOLEAN (WINAPI *pCreateSymbolicLinkW)(const WCHAR *, const WCHAR *, DWORD);
static HMODULE msvcp; @@ -291,6 +311,9 @@ static BOOL init(void) SET(p__Release_chore, "?_Release_chore@details@Concurrency@@YAXPEAU_Threadpool_chore@12@@Z"); SET(p__Winerror_message, "?_Winerror_message@std@@YAKKPEADK@Z"); SET(p__Syserror_map, "?_Syserror_map@std@@YAPEBDH@Z"); + + SET(p__Fiopen_wchar, "?_Fiopen@std@@YAPEAU_iobuf@@PEB_WHH@Z"); + SET(p__Fiopen, "?_Fiopen@std@@YAPEAU_iobuf@@PEBDHH@Z"); } else { #ifdef __arm__ SET(p_task_continuation_context_ctor, "??0task_continuation_context@Concurrency@@AAA@XZ"); @@ -322,6 +345,9 @@ static BOOL init(void) SET(p__Release_chore, "?_Release_chore@details@Concurrency@@YAXPAU_Threadpool_chore@12@@Z"); SET(p__Winerror_message, "?_Winerror_message@std@@YAKKPADK@Z"); SET(p__Syserror_map, "?_Syserror_map@std@@YAPBDH@Z"); + + SET(p__Fiopen_wchar, "?_Fiopen@std@@YAPAU_iobuf@@PB_WHH@Z"); + SET(p__Fiopen, "?_Fiopen@std@@YAPAU_iobuf@@PBDHH@Z"); }
SET(p__Mtx_init, "_Mtx_init"); @@ -365,6 +391,11 @@ static BOOL init(void) hdll = GetModuleHandleA("kernel32.dll"); pCreateSymbolicLinkW = (void*)GetProcAddress(hdll, "CreateSymbolicLinkW");
+ hdll = GetModuleHandleA("ucrtbase.dll"); + p_setlocale = (void*)GetProcAddress(hdll, "setlocale"); + p_fclose = (void*)GetProcAddress(hdll, "fclose"); + p__unlink = (void*)GetProcAddress(hdll, "_unlink"); + init_thiscall_thunk(); return TRUE; } @@ -1670,6 +1701,48 @@ static void test__Mtx(void) p__Mtx_destroy(mtx); }
+static void test__Fiopen(void) +{ + int i; + FILE *f; + wchar_t wpath[MAX_PATH]; + 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 }, + }; + + for(i=0; i<ARRAY_SIZE(tests); i++) { + if(!p_setlocale(LC_ALL, tests[i].loc)) { + win_skip("skipping locale %s\n", tests[i].loc); + continue; + } + + ok(MultiByteToWideChar(CP_UTF8, 0, tests[i].path, -1, wpath, MAX_PATH), + "MultiByteToWideChar failed on %s with locale %s: %lx\n", + debugstr_a(tests[i].path), tests[i].loc, GetLastError()); + + f = p__Fiopen(tests[i].path, OPENMODE_out, SH_DENYNO); + ok(!!f, "failed to create %s with locale %s\n", tests[i].path, tests[i].loc); + p_fclose(f); + + f = p__Fiopen_wchar(wpath, OPENMODE_in, SH_DENYNO); + todo_wine_if(tests[i].is_todo) + ok(!!f, "failed to open %s with locale %s\n", wine_dbgstr_w(wpath), tests[i].loc); + if(f) p_fclose(f); + + p__unlink(tests[i].path); + } + p_setlocale(LC_ALL, "C"); +} + START_TEST(msvcp140) { if(!init()) return; @@ -1698,5 +1771,6 @@ START_TEST(msvcp140) test_cnd(); test_Copy_file(); test__Mtx(); + test__Fiopen(); FreeLibrary(msvcp); }
From: Daniel Lehman dlehman25@gmail.com
--- dlls/msvcp90/ios.c | 54 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 8 deletions(-)
diff --git a/dlls/msvcp90/ios.c b/dlls/msvcp90/ios.c index 5b791cd4345..80e7694bd0f 100644 --- a/dlls/msvcp90/ios.c +++ b/dlls/msvcp90/ios.c @@ -3268,18 +3268,56 @@ FILE* __cdecl _Fiopen_wchar(const wchar_t *name, int mode, int prot) /* ?_Fiopen@std@@YAPEAU_iobuf@@PEBDHH@Z */ FILE* __cdecl _Fiopen(const char *name, int mode, int prot) { - wchar_t nameW[FILENAME_MAX]; + static const struct { + int mode; + const char str[4]; + const char str_bin[4]; + } str_mode[] = { + {OPENMODE_out, "w", "wb"}, + {OPENMODE_out|OPENMODE_app, "a", "ab"}, + {OPENMODE_app, "a", "ab"}, + {OPENMODE_out|OPENMODE_trunc, "w", "wb"}, + {OPENMODE_in, "r", "rb"}, + {OPENMODE_in|OPENMODE_out, "r+", "r+b"}, + {OPENMODE_in|OPENMODE_out|OPENMODE_trunc, "w+", "w+b"}, + {OPENMODE_in|OPENMODE_out|OPENMODE_app, "a+", "a+b"}, + {OPENMODE_in|OPENMODE_app, "a+", "a+b"} + };
- TRACE("(%s %d %d)\n", name, mode, prot); + int real_mode = mode & ~(OPENMODE_ate|OPENMODE__Nocreate|OPENMODE__Noreplace|OPENMODE_binary); + size_t mode_idx; + FILE *f = NULL;
-#if _MSVCP_VER >= 80 && _MSVCP_VER <= 90 - if(mbstowcs_s(NULL, nameW, FILENAME_MAX, name, FILENAME_MAX-1) != 0) + TRACE("(%s %d %d)\n", debugstr_a(name), mode, prot); + + for(mode_idx=0; mode_idx<ARRAY_SIZE(str_mode); mode_idx++) + if(str_mode[mode_idx].mode == real_mode) + break; + if(mode_idx == ARRAY_SIZE(str_mode)) return NULL; -#else - if(!MultiByteToWideChar(CP_ACP, 0, name, -1, nameW, FILENAME_MAX-1)) + + if((mode & OPENMODE__Nocreate) && !(f = fopen(name, "r"))) return NULL; -#endif - return _Fiopen_wchar(nameW, mode, prot); + else if(f) + fclose(f); + + if((mode & OPENMODE__Noreplace) && (mode & (OPENMODE_out|OPENMODE_app)) + && (f = fopen(name, "r"))) { + fclose(f); + return NULL; + } + + f = _fsopen(name, (mode & OPENMODE_binary) ? str_mode[mode_idx].str_bin + : str_mode[mode_idx].str, prot); + if(!f) + return NULL; + + if((mode & OPENMODE_ate) && fseek(f, 0, SEEK_END)) { + fclose(f); + return NULL; + } + + return f; }
/* ?__Fiopen@std@@YAPAU_iobuf@@PBDH@Z */
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=150045
Your paranoid android.
=== w10pro64_en_AE_u8 (32 bit report) ===
ucrtbase: file.c:204: Test failed: failed to create "t\xb8\xd5.txt" with locale Japanese
Report validation errors: ucrtbase:file crashed (c0000409)
=== debian11 (32 bit hi:IN report) ===
msvcp140: msvcp140.c:1738: Test succeeded inside todo block: failed to open L"t\00e4\00cf\00f6\00df.txt" with locale German.utf8 msvcp140.c:1738: Test succeeded inside todo block: failed to open L"t\0119\015b\0107.txt" with locale Polish.utf8 msvcp140.c:1738: Test succeeded inside todo block: failed to open L"t\00c7\011e\0131\0130\015e.txt" with locale Turkish.utf8 msvcp140.c:1738: Test succeeded inside todo block: failed to open L"t\062a\0686.txt" with locale Arabic.utf8 msvcp140.c:1738: Test succeeded inside todo block: failed to open L"t\30af\30e4.txt" with locale Japanese.utf8 msvcp140.c:1738: Test succeeded inside todo block: failed to open L"t\4e02\9f6b.txt" with locale Chinese.utf8
ucrtbase: file.c:210: Test succeeded inside todo block: failed to open "t\xc3\xa4\xc3\x8f\xc3\xb6\xc3\x9f.txt" with locale German.utf8 file.c:210: Test succeeded inside todo block: failed to open "t\xc4\x99\xc5\x9b\xc4\x87.txt" with locale Polish.utf8 file.c:210: Test succeeded inside todo block: failed to open "t\xc3\x87\xc4\x9e\xc4\xb1\xc4\xb0\xc5\x9e.txt" with locale Turkish.utf8 file.c:210: Test succeeded inside todo block: failed to open "t\xd8\xaa\xda\x86.txt" with locale Arabic.utf8 file.c:210: Test succeeded inside todo block: failed to open "t\xe3\x82\xaf\xe3\x83\xa4.txt" with locale Japanese.utf8 file.c:210: Test succeeded inside todo block: failed to open "t\xe4\xb8\x82\xe9\xbd\xab.txt" with locale Chinese.utf8
=== debian11b (64 bit WoW report) ===
user32: win.c:4070: Test failed: Expected active window 000000000238016C, got 0000000000000000. win.c:4071: Test failed: Expected focus window 000000000238016C, got 0000000000000000.