mirror of
https://gitlab.winehq.org/wine/wine.git
synced 2024-11-19 17:06:04 -07:00
Merge branch 'fiopenutf8' into 'master'
msvcp140: Use current locale to convert path in _Fiopen. See merge request wine/wine!6680
This commit is contained in:
commit
166abeb933
3 changed files with 258 additions and 0 deletions
|
@ -20,9 +20,11 @@
|
|||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
#include <share.h>
|
||||
|
||||
#include "wine/test.h"
|
||||
#include "winbase.h"
|
||||
#include "winnls.h"
|
||||
|
||||
DWORD expect_idx;
|
||||
static int vector_alloc_count;
|
||||
|
@ -210,6 +212,7 @@ static BOOL compare_float(float f, float g, unsigned int ulps)
|
|||
static char* (__cdecl *p_setlocale)(int, const char*);
|
||||
static int (__cdecl *p__setmbcp)(int);
|
||||
static int (__cdecl *p__ismbblead)(unsigned int);
|
||||
static int (__cdecl *p_fclose)(FILE*);
|
||||
|
||||
static MSVCRT_long (__cdecl *p__Xtime_diff_to_millis2)(const xtime*, const xtime*);
|
||||
static int (__cdecl *p_xtime_get)(xtime*, int);
|
||||
|
@ -423,6 +426,20 @@ static void (__thiscall *p_vector_base_v4__Internal_resize)(
|
|||
|
||||
static const BYTE *p_byte_reverse_table;
|
||||
|
||||
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 HMODULE msvcp;
|
||||
#define SETNOFAIL(x,y) x = (void*)GetProcAddress(msvcp,y)
|
||||
#define SET(x,y) do { SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y); } while(0)
|
||||
|
@ -584,6 +601,10 @@ static BOOL init(void)
|
|||
"?_Internal_resize@_Concurrent_vector_base_v4@details@Concurrency@@IEAAX_K00P6AXPEAX0@ZP6AX1PEBX0@Z3@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 {
|
||||
SET(p_tr2_sys__File_size,
|
||||
"?_File_size@sys@tr2@std@@YA_KPBD@Z");
|
||||
|
@ -659,6 +680,10 @@ static BOOL init(void)
|
|||
"?_Segment_index_of@_Concurrent_vector_base_v4@details@Concurrency@@KAII@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");
|
||||
#ifdef __i386__
|
||||
SET(p_i386_Thrd_current,
|
||||
"_Thrd_current");
|
||||
|
@ -821,6 +846,7 @@ static BOOL init(void)
|
|||
p_setlocale = (void*)GetProcAddress(hdll, "setlocale");
|
||||
p__setmbcp = (void*)GetProcAddress(hdll, "_setmbcp");
|
||||
p__ismbblead = (void*)GetProcAddress(hdll, "_ismbblead");
|
||||
p_fclose = (void*)GetProcAddress(hdll, "fclose");
|
||||
|
||||
hdll = GetModuleHandleA("kernel32.dll");
|
||||
pCreateSymbolicLinkA = (void*)GetProcAddress(hdll, "CreateSymbolicLinkA");
|
||||
|
@ -3343,6 +3369,96 @@ static void test_data_exports(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void test__Fiopen(void)
|
||||
{
|
||||
int i;
|
||||
FILE *f;
|
||||
char apath[MAX_PATH];
|
||||
wchar_t wpath[MAX_PATH];
|
||||
static const struct {
|
||||
const char *loc;
|
||||
UINT cp;
|
||||
const WCHAR *path;
|
||||
} tests[] = {
|
||||
{ "German", 1252, L"t\x00e4\x00cf\x00f6\x00df.txt" },
|
||||
{ "Polish", 1250, L"t\x0119\x015b\x0107.txt" },
|
||||
{ "Turkish", 1254, L"t\x00c7\x011e\x0131\x0130\x015e.txt" },
|
||||
{ "Arabic", 1256, L"t\x062a\x0686.txt" },
|
||||
{ "Japanese", 932, L"t\x30af\x30e4.txt" },
|
||||
{ "Chinese", 936, L"t\x4e02\x9f6b.txt" },
|
||||
};
|
||||
static const struct {
|
||||
const char *loc;
|
||||
UINT cp;
|
||||
const char *path;
|
||||
} tests_a[] = {
|
||||
{ "German", 1252, "t\xe4\xcf\xf6\xdf.txt" },
|
||||
{ "Polish", 1250, "t\xea\x9c\xe6.txt" },
|
||||
{ "Turkish", 1254, "t\xd0\xf0\xdd\xde\xfd\xfe.txt" },
|
||||
{ "Arabic", 1256, "t\xca\x8c.txt" },
|
||||
{ "Japanese", 932, "t\xb8\xd5.txt" },
|
||||
{ "Chinese", 936, "t\x81\x40\xfd\x71.txt" },
|
||||
};
|
||||
|
||||
/* w -> a */
|
||||
for(i=0; i<ARRAY_SIZE(tests); i++) {
|
||||
if(GetACP() != tests[i].cp) {
|
||||
skip("skipping test for %u (current %u)\n", tests[i].cp, GetACP());
|
||||
continue;
|
||||
}
|
||||
if(!p_setlocale(LC_ALL, tests[i].loc)) {
|
||||
win_skip("skipping locale %s\n", tests[i].loc);
|
||||
continue;
|
||||
}
|
||||
if(!WideCharToMultiByte(CP_ACP, 0, tests[i].path, -1,
|
||||
apath, sizeof(apath), NULL, NULL)) {
|
||||
win_skip("failed to convert %s with locale %s\n",
|
||||
wine_dbgstr_w(tests[i].path), tests[i].loc);
|
||||
continue;
|
||||
}
|
||||
|
||||
f = p__Fiopen_wchar(tests[i].path, OPENMODE_out, SH_DENYNO);
|
||||
ok(!!f, "failed to create %s with locale %s\n",
|
||||
wine_dbgstr_w(tests[i].path), tests[i].loc);
|
||||
p_fclose(f);
|
||||
|
||||
f = p__Fiopen(apath, OPENMODE_in, SH_DENYNO);
|
||||
ok(!!f, "failed to read %s with locale %s\n", apath, tests[i].loc);
|
||||
p_fclose(f);
|
||||
|
||||
DeleteFileW(tests[i].path);
|
||||
}
|
||||
|
||||
/* a -> w */
|
||||
for(i=0; i<ARRAY_SIZE(tests_a); i++) {
|
||||
if(tests_a[i].cp != GetACP()) {
|
||||
skip("skipping test for %u (current %u)\n", tests_a[i].cp, GetACP());
|
||||
continue;
|
||||
}
|
||||
if(!p_setlocale(LC_ALL, tests_a[i].loc)) {
|
||||
win_skip("skipping locale %s\n", tests_a[i].loc);
|
||||
continue;
|
||||
}
|
||||
if(!MultiByteToWideChar(CP_ACP, 0, tests_a[i].path, -1,
|
||||
wpath, ARRAY_SIZE(wpath))) {
|
||||
win_skip("failed to convert %s with locale %s\n",
|
||||
tests_a[i].path, tests_a[i].loc);
|
||||
continue;
|
||||
}
|
||||
|
||||
f = p__Fiopen(tests_a[i].path, OPENMODE_out, SH_DENYNO);
|
||||
ok(!!f, "failed to create %s with locale %s\n", tests_a[i].path, tests_a[i].loc);
|
||||
p_fclose(f);
|
||||
|
||||
f = p__Fiopen_wchar(wpath, OPENMODE_in, SH_DENYNO);
|
||||
ok(!!f, "failed to read %s with locale %s\n", wine_dbgstr_w(wpath), tests_a[i].loc);
|
||||
p_fclose(f);
|
||||
|
||||
DeleteFileA(tests_a[i].path);
|
||||
}
|
||||
p_setlocale(LC_ALL, "C");
|
||||
}
|
||||
|
||||
START_TEST(msvcp120)
|
||||
{
|
||||
if(!init()) return;
|
||||
|
@ -3390,6 +3506,8 @@ START_TEST(msvcp120)
|
|||
|
||||
test_data_exports();
|
||||
|
||||
test__Fiopen();
|
||||
|
||||
free_expect_struct();
|
||||
TlsFree(expect_idx);
|
||||
FreeLibrary(msvcp);
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winnls.h"
|
||||
#include "share.h"
|
||||
#include "locale.h"
|
||||
|
||||
#include "wine/test.h"
|
||||
#include "winbase.h"
|
||||
|
@ -253,6 +255,23 @@ 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 BOOLEAN (WINAPI *pCreateSymbolicLinkW)(const WCHAR *, const WCHAR *, DWORD);
|
||||
|
||||
static HMODULE msvcp;
|
||||
|
@ -291,6 +310,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 +344,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");
|
||||
|
@ -362,6 +387,10 @@ static BOOL init(void)
|
|||
SET(p_To_wide, "_To_wide");
|
||||
SET(p_Unlink, "_Unlink");
|
||||
|
||||
hdll = GetModuleHandleA("ucrtbase.dll");
|
||||
p_setlocale = (void*)GetProcAddress(hdll, "setlocale");
|
||||
p_fclose = (void*)GetProcAddress(hdll, "fclose");
|
||||
|
||||
hdll = GetModuleHandleA("kernel32.dll");
|
||||
pCreateSymbolicLinkW = (void*)GetProcAddress(hdll, "CreateSymbolicLinkW");
|
||||
|
||||
|
@ -1670,6 +1699,110 @@ static void test__Mtx(void)
|
|||
p__Mtx_destroy(mtx);
|
||||
}
|
||||
|
||||
static void test__Fiopen(void)
|
||||
{
|
||||
int i;
|
||||
FILE *f;
|
||||
char apath[MAX_PATH];
|
||||
wchar_t wpath[MAX_PATH];
|
||||
static const struct {
|
||||
const char *loc;
|
||||
UINT cp;
|
||||
const WCHAR *path;
|
||||
} tests[] = {
|
||||
{ "German.utf8", 0, L"t\x00e4\x00cf\x00f6\x00df.txt" },
|
||||
{ "Polish.utf8", 0, L"t\x0119\x015b\x0107.txt" },
|
||||
{ "Turkish.utf8", 0, L"t\x00c7\x011e\x0131\x0130\x015e.txt" },
|
||||
{ "Arabic.utf8", 0, L"t\x062a\x0686.txt" },
|
||||
{ "Japanese.utf8", 0, L"t\x30af\x30e4.txt" },
|
||||
{ "Chinese.utf8", 0, L"t\x4e02\x9f6b.txt" },
|
||||
|
||||
{ "German.1252", 1252, L"t\x00e4\x00cf\x00f6\x00df.txt" },
|
||||
{ "Polish.1250", 1250, L"t\x0119\x015b\x0107.txt" },
|
||||
{ "Turkish.1254", 1254, L"t\x00c7\x011e\x0131\x0130\x015e.txt" },
|
||||
{ "Arabic.1256", 1256, L"t\x062a\x0686.txt" },
|
||||
{ "Japanese.932", 932, L"t\x30af\x30e4.txt" },
|
||||
{ "Chinese.936", 936, L"t\x4e02\x9f6b.txt" },
|
||||
};
|
||||
static const struct {
|
||||
const char *loc;
|
||||
UINT cp;
|
||||
const char *path;
|
||||
} tests_a[] = {
|
||||
{ "German.utf8", 0, "t\xc3\xa4\xc3\x8f\xc3\xb6\xc3\x9f.txt" },
|
||||
{ "Polish.utf8", 0, "t\xc4\x99\xc5\x9b\xc4\x87.txt" },
|
||||
{ "Turkish.utf8", 0, "t\xc3\x87\xc4\x9e\xc4\xb1\xc4\xb0\xc5\x9e.txt" },
|
||||
{ "Arabic.utf8", 0, "t\xd8\xaa\xda\x86.txt" },
|
||||
{ "Japanese.utf8", 0, "t\xe3\x82\xaf\xe3\x83\xa4.txt" },
|
||||
{ "Chinese.utf8", 0, "t\xe4\xb8\x82\xe9\xbd\xab.txt" },
|
||||
|
||||
{ "German.1252", 1252, "t\xe4\xcf\xf6\xdf.txt" },
|
||||
{ "Polish.1250", 1250, "t\xea\x9c\xe6.txt" },
|
||||
{ "Turkish.1254", 1254, "t\xd0\xf0\xdd\xde\xfd\xfe.txt" },
|
||||
{ "Arabic.1256", 1256, "t\xca\x8c.txt" },
|
||||
{ "Japanese.932", 932, "t\xb8\xd5.txt" },
|
||||
{ "Chinese.936", 936, "t\x81\x40\xfd\x71.txt" },
|
||||
};
|
||||
|
||||
/* w -> a */
|
||||
for(i=0; i<ARRAY_SIZE(tests); i++) {
|
||||
if(tests[i].cp && GetACP() != tests[i].cp) {
|
||||
skip("skipping test for %u (current %u)\n", tests[i].cp, GetACP());
|
||||
continue;
|
||||
}
|
||||
if(!p_setlocale(LC_ALL, tests[i].loc)) {
|
||||
win_skip("skipping locale %s\n", tests[i].loc);
|
||||
continue;
|
||||
}
|
||||
if(!WideCharToMultiByte(tests[i].cp ? CP_ACP : CP_UTF8, 0, tests[i].path, -1,
|
||||
apath, sizeof(apath), NULL, NULL)) {
|
||||
win_skip("failed to convert %s with locale %s\n",
|
||||
wine_dbgstr_w(tests[i].path), tests[i].loc);
|
||||
continue;
|
||||
}
|
||||
|
||||
f = p__Fiopen_wchar(tests[i].path, OPENMODE_out, SH_DENYNO);
|
||||
ok(!!f, "failed to create %s with locale %s\n",
|
||||
wine_dbgstr_w(tests[i].path), tests[i].loc);
|
||||
p_fclose(f);
|
||||
|
||||
f = p__Fiopen(apath, OPENMODE_in, SH_DENYNO);
|
||||
ok(!!f, "failed to read %s with locale %s\n", apath, tests[i].loc);
|
||||
if(f) p_fclose(f);
|
||||
|
||||
DeleteFileW(tests[i].path);
|
||||
}
|
||||
|
||||
/* a -> w */
|
||||
for(i=0; i<ARRAY_SIZE(tests_a); i++) {
|
||||
if(tests_a[i].cp && tests_a[i].cp != GetACP()) {
|
||||
skip("skipping test for %u (current %u)\n", tests_a[i].cp, GetACP());
|
||||
continue;
|
||||
}
|
||||
if(!p_setlocale(LC_ALL, tests_a[i].loc)) {
|
||||
win_skip("skipping locale %s\n", tests_a[i].loc);
|
||||
continue;
|
||||
}
|
||||
if(!MultiByteToWideChar(tests_a[i].cp ? CP_ACP : CP_UTF8, 0, tests_a[i].path, -1,
|
||||
wpath, ARRAY_SIZE(wpath))) {
|
||||
win_skip("failed to convert %s with locale %s\n",
|
||||
tests_a[i].path, tests_a[i].loc);
|
||||
continue;
|
||||
}
|
||||
|
||||
f = p__Fiopen(tests_a[i].path, OPENMODE_out, SH_DENYNO);
|
||||
ok(!!f, "failed to create %s with locale %s\n", tests_a[i].path, tests_a[i].loc);
|
||||
p_fclose(f);
|
||||
|
||||
f = p__Fiopen_wchar(wpath, OPENMODE_in, SH_DENYNO);
|
||||
ok(!!f, "failed to read %s with locale %s\n", wine_dbgstr_w(wpath), tests_a[i].loc);
|
||||
if(f) p_fclose(f);
|
||||
|
||||
DeleteFileA(tests_a[i].path);
|
||||
}
|
||||
p_setlocale(LC_ALL, "C");
|
||||
}
|
||||
|
||||
START_TEST(msvcp140)
|
||||
{
|
||||
if(!init()) return;
|
||||
|
@ -1698,5 +1831,6 @@ START_TEST(msvcp140)
|
|||
test_cnd();
|
||||
test_Copy_file();
|
||||
test__Mtx();
|
||||
test__Fiopen();
|
||||
FreeLibrary(msvcp);
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(msvcp);
|
||||
|
||||
unsigned int __cdecl ___lc_codepage_func(void);
|
||||
|
||||
#define SECSPERDAY 86400
|
||||
/* 1601 to 1970 is 369 years plus 89 leap days */
|
||||
#define SECS_1601_TO_1970 ((369 * 365 + 89) * (ULONGLONG)SECSPERDAY)
|
||||
|
@ -3275,6 +3277,10 @@ FILE* __cdecl _Fiopen(const char *name, int mode, int prot)
|
|||
#if _MSVCP_VER >= 80 && _MSVCP_VER <= 90
|
||||
if(mbstowcs_s(NULL, nameW, FILENAME_MAX, name, FILENAME_MAX-1) != 0)
|
||||
return NULL;
|
||||
#elif _MSVCP_VER >= 140
|
||||
if(!MultiByteToWideChar(___lc_codepage_func() == CP_UTF8 ? CP_UTF8 : CP_ACP,
|
||||
0, name, -1, nameW, FILENAME_MAX-1))
|
||||
return NULL;
|
||||
#else
|
||||
if(!MultiByteToWideChar(CP_ACP, 0, name, -1, nameW, FILENAME_MAX-1))
|
||||
return NULL;
|
||||
|
|
Loading…
Reference in a new issue