From: Paul Gofman <pgofman(a)codeweavers.com> --- dlls/msvcp140/msvcp140.spec | 6 +-- dlls/msvcp140/tests/msvcp140.c | 90 +++++++++++++++++++++++++++++++++- dlls/msvcp90/locale.c | 48 ++++++++++-------- dlls/msvcp90/msvcp90.h | 2 + 4 files changed, 121 insertions(+), 25 deletions(-) diff --git a/dlls/msvcp140/msvcp140.spec b/dlls/msvcp140/msvcp140.spec index 600cbfa345c..0a8af0ec04b 100644 --- a/dlls/msvcp140/msvcp140.spec +++ b/dlls/msvcp140/msvcp140.spec @@ -175,9 +175,9 @@ @ cdecl -arch=arm ??0?$codecvt(a)_SDU_Mbstatet@@@std@@QAA(a)ABV_Locinfo@1(a)I@Z(ptr ptr long) codecvt_char16_ctor_locinfo @ thiscall -arch=i386 ??0?$codecvt(a)_SDU_Mbstatet@@@std@@QAE(a)ABV_Locinfo@1(a)I@Z(ptr ptr long) codecvt_char16_ctor_locinfo @ cdecl -arch=win64 ??0?$codecvt(a)_SDU_Mbstatet@@@std@@QEAA(a)AEBV_Locinfo@1(a)_K@Z(ptr ptr long) codecvt_char16_ctor_locinfo -@ cdecl -arch=arm ??0?$codecvt(a)_SDU_Mbstatet@@@std@@QAA(a)ABV_Locinfo@1(a)KW4_Codecvt_mode@1(a)I@Z(ptr long long long) codecvt_char16_ctor_mode -@ thiscall -arch=i386 ??0?$codecvt(a)_SDU_Mbstatet@@@std@@QAE(a)ABV_Locinfo@1(a)KW4_Codecvt_mode@1(a)I@Z(ptr long long long) codecvt_char16_ctor_mode -@ cdecl -arch=win64 ??0?$codecvt(a)_SDU_Mbstatet@@@std@@QEAA(a)AEBV_Locinfo@1(a)KW4_Codecvt_mode@1(a)_K@Z(ptr long long long) codecvt_char16_ctor_mode +@ cdecl -arch=arm ??0?$codecvt(a)_SDU_Mbstatet@@@std@@QAA(a)ABV_Locinfo@1(a)KW4_Codecvt_mode@1(a)I@Z(ptr ptr long long long) codecvt_char16_ctor_mode +@ thiscall -arch=i386 ??0?$codecvt(a)_SDU_Mbstatet@@@std@@QAE(a)ABV_Locinfo@1(a)KW4_Codecvt_mode@1(a)I@Z(ptr ptr long long long) codecvt_char16_ctor_mode +@ cdecl -arch=win64 ??0?$codecvt(a)_SDU_Mbstatet@@@std@@QEAA(a)AEBV_Locinfo@1(a)KW4_Codecvt_mode@1(a)_K@Z(ptr ptr long long long) codecvt_char16_ctor_mode @ cdecl -arch=arm ??0?$codecvt(a)_SDU_Mbstatet@@@std@@QAA(a)I@Z(ptr long) codecvt_char16_ctor_refs @ thiscall -arch=i386 ??0?$codecvt(a)_SDU_Mbstatet@@@std@@QAE(a)I@Z(ptr long) codecvt_char16_ctor_refs @ cdecl -arch=win64 ??0?$codecvt(a)_SDU_Mbstatet@@@std@@QEAA(a)_K@Z(ptr long) codecvt_char16_ctor_refs diff --git a/dlls/msvcp140/tests/msvcp140.c b/dlls/msvcp140/tests/msvcp140.c index b1ab13fe80b..bc65d80bb85 100644 --- a/dlls/msvcp140/tests/msvcp140.c +++ b/dlls/msvcp140/tests/msvcp140.c @@ -89,6 +89,8 @@ struct thiscall_thunk static void * (WINAPI *call_thiscall_func1)( void *func, void *this ); static void * (WINAPI *call_thiscall_func2)( void *func, void *this, const void *a ); +static void * (WINAPI *call_thiscall_func5)( void *func, void *this, const void *a, const void *b, + const void *c, const void *d ); static void init_thiscall_thunk(void) { @@ -101,16 +103,20 @@ static void init_thiscall_thunk(void) thunk->jmp_edx = 0xe2ff; /* jmp *%edx */ call_thiscall_func1 = (void *)thunk; call_thiscall_func2 = (void *)thunk; + call_thiscall_func5 = (void *)thunk; } #define call_func1(func,_this) call_thiscall_func1(func,_this) -#define call_func2(func,_this,a) call_thiscall_func2(func,_this,a) +#define call_func2(func,_this,a) call_thiscall_func2(func,_this,(const void*)(a)) +#define call_func5(func,_this,a,b,c,d) call_thiscall_func5(func,_this,(const void*)(a),(const void*)(b), \ + (const void*)(c), (const void*)(d)) #else #define init_thiscall_thunk() #define call_func1(func,_this) func(_this) #define call_func2(func,_this,a) func(_this,a) +#define call_func5(func,_this,a,b,c,d) func(_this,a,b,c,d) #endif /* __i386__ */ typedef unsigned char MSVCP_bool; @@ -284,6 +290,40 @@ static int (__cdecl *p__unlink)(const char*); static BOOLEAN (WINAPI *pCreateSymbolicLinkW)(const WCHAR *, const WCHAR *, DWORD); +typedef void (*vtable_ptr)(void); +typedef SIZE_T MSVCP_size_t; + +/* class locale::facet */ +typedef struct { + const vtable_ptr *vtable; + unsigned int refs; +} locale_facet; + +/* class codecvt_base */ +typedef struct { + locale_facet facet; +} codecvt_base; + +typedef enum convert_mode +{ + consume_header = 4, + generate_header = 2, + little_endian = 1 +} codecvt_convert_mode; + +/* class codecvt<char16> */ +typedef struct { + codecvt_base base; + unsigned int max_code; + codecvt_convert_mode convert_mode; +} codecvt_char16; + +static codecvt_char16 *(__thiscall * p_codecvt_char16_ctor)(codecvt_char16 *this); +static codecvt_char16 *(__thiscall * p_codecvt_char16_ctor_refs)(codecvt_char16 *this, unsigned int refs); +static codecvt_char16 * (__thiscall * p_codecvt_char16_ctor_mode)(codecvt_char16 *this, void *locinfo, + ULONG max_code, codecvt_convert_mode mode, unsigned int refs); +static void (__thiscall * p_codecvt_char16_dtor)(codecvt_char16 *this); + 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) @@ -323,6 +363,10 @@ static BOOL init(void) SET(p__Fiopen_wchar, "?_Fiopen(a)std@@YAPEAU_iobuf@@PEB_WHH(a)Z"); SET(p__Fiopen, "?_Fiopen(a)std@@YAPEAU_iobuf@@PEBDHH(a)Z"); + SET(p_codecvt_char16_ctor, "??_F?$codecvt(a)_SDU_Mbstatet@@@std@@QEAAXXZ"); + SET(p_codecvt_char16_ctor_refs, "??0?$codecvt(a)_SDU_Mbstatet@@@std@@QEAA(a)_K@Z"); + SET(p_codecvt_char16_ctor_mode, "??0?$codecvt(a)_SDU_Mbstatet@@@std@@QEAA(a)AEBV_Locinfo@1(a)KW4_Codecvt_mode@1(a)_K@Z"); + SET(p_codecvt_char16_dtor, "??1?$codecvt(a)_SDU_Mbstatet@@@std@@MEAA(a)XZ"); } else { #ifdef __arm__ SET(p_task_continuation_context_ctor, "??0task_continuation_context(a)Concurrency@@AAA(a)XZ"); @@ -336,6 +380,10 @@ static BOOL init(void) SET(p__TaskEventLogger__LogTaskExecutionCompleted, "?_LogTaskExecutionCompleted(a)_TaskEventLogger@details(a)Concurrency@@QAAXXZ"); SET(p__TaskEventLogger__LogWorkItemCompleted, "?_LogWorkItemCompleted(a)_TaskEventLogger@details(a)Concurrency@@QAAXXZ"); SET(p__TaskEventLogger__LogWorkItemStarted, "?_LogWorkItemStarted(a)_TaskEventLogger@details(a)Concurrency@@QAAXXZ"); + SET(p_codecvt_char16_ctor, "??_F?$codecvt(a)_SDU_Mbstatet@@@std@@QAAXXZ"); + SET(p_codecvt_char16_ctor_refs, "??0?$codecvt(a)_SDU_Mbstatet@@@std@@QAA(a)I@Z"); + SET(p_codecvt_char16_ctor_mode, "??0?$codecvt(a)_SDU_Mbstatet@@@std@@QAA(a)ABV_Locinfo@1(a)KW4_Codecvt_mode@1(a)I@Z"); + SET(p_codecvt_char16_dtor, "??1?$codecvt(a)_SDU_Mbstatet@@@std@@MAA(a)XZ(ptr)"); #else SET(p_task_continuation_context_ctor, "??0task_continuation_context(a)Concurrency@@AAE(a)XZ"); SET(p__ContextCallback__Assign, "?_Assign(a)_ContextCallback@details(a)Concurrency@@AAEXPAX(a)Z"); @@ -348,6 +396,10 @@ static BOOL init(void) SET(p__TaskEventLogger__LogTaskExecutionCompleted, "?_LogTaskExecutionCompleted(a)_TaskEventLogger@details(a)Concurrency@@QAEXXZ"); SET(p__TaskEventLogger__LogWorkItemCompleted, "?_LogWorkItemCompleted(a)_TaskEventLogger@details(a)Concurrency@@QAEXXZ"); SET(p__TaskEventLogger__LogWorkItemStarted, "?_LogWorkItemStarted(a)_TaskEventLogger@details(a)Concurrency@@QAEXXZ"); + SET(p_codecvt_char16_ctor, "??_F?$codecvt(a)_SDU_Mbstatet@@@std@@QAEXXZ"); + SET(p_codecvt_char16_ctor_refs, "??0?$codecvt(a)_SDU_Mbstatet@@@std@@QAE(a)I@Z"); + SET(p_codecvt_char16_ctor_mode, "??0?$codecvt(a)_SDU_Mbstatet@@@std@@QAE(a)ABV_Locinfo@1(a)KW4_Codecvt_mode@1(a)I@Z"); + SET(p_codecvt_char16_dtor, "??1?$codecvt(a)_SDU_Mbstatet@@@std@@MAE(a)XZ"); #endif SET(p__Schedule_chore, "?_Schedule_chore(a)details@Concurrency@@YAHPAU_Threadpool_chore(a)12@@Z"); SET(p__Reschedule_chore, "?_Reschedule_chore(a)details@Concurrency@@YAHPBU_Threadpool_chore(a)12@@Z"); @@ -1810,6 +1862,41 @@ static void test__Fiopen(void) p_setlocale(LC_ALL, "C"); } +void test_codecvt_char16(void) +{ + char buffer[256]; + codecvt_char16 *this, *this2; + + this = (codecvt_char16 *)buffer; + memset(buffer, 0xcc, sizeof(buffer)); + this2 = call_func1(p_codecvt_char16_ctor, this); + ok(!this->base.facet.refs, "got %u.\n", this->base.facet.refs); + ok(this->convert_mode == consume_header, "got %#x.\n", this->max_code); + ok(this->max_code == MAX_UCSCHAR, "got %#x.\n", this->max_code); + ok(*(unsigned int *)(buffer + sizeof(*this)) == 0xcccccccc, "got %#x.\n", *(unsigned int *)(buffer + sizeof(*this))); + call_func1(p_codecvt_char16_dtor, this); + + this = (codecvt_char16 *)buffer; + memset(buffer, 0xcc, sizeof(buffer)); + this2 = call_func2(p_codecvt_char16_ctor_refs, this, 12); + ok(this2 == this, "got %p, %p.\n", this2, this); + ok(this->base.facet.refs == 12, "got %u.\n", this->base.facet.refs); + ok(this->convert_mode == consume_header, "got %#x.\n", this->max_code); + ok(this->max_code == MAX_UCSCHAR, "got %#x.\n", this->max_code); + ok(*(unsigned int *)(buffer + sizeof(*this)) == 0xcccccccc, "got %#x.\n", *(unsigned int *)(buffer + sizeof(*this))); + call_func1(p_codecvt_char16_dtor, this); + + this = (codecvt_char16 *)buffer; + memset(buffer, 0xcc, sizeof(buffer)); + this2 = call_func5(p_codecvt_char16_ctor_mode, this, (void *)0xdeadbeef, 0x55, 0x44, 12); + ok(this2 == this, "got %p, %p.\n", this2, this); + ok(this->base.facet.refs == 12, "got %#x.\n", this->base.facet.refs); + ok(this->convert_mode == 0x44, "got %#x.\n", this->convert_mode); + ok(this->max_code == 0x55, "got %#x.\n", this->max_code); + ok(*(unsigned int *)(buffer + sizeof(*this)) == 0xcccccccc, "got %#x.\n", *(unsigned int *)(buffer + sizeof(*this))); + call_func1(p_codecvt_char16_dtor, this); +} + START_TEST(msvcp140) { if(!init()) return; @@ -1839,5 +1926,6 @@ START_TEST(msvcp140) test_Copy_file(); test__Mtx(); test__Fiopen(); + test_codecvt_char16(); FreeLibrary(msvcp); } diff --git a/dlls/msvcp90/locale.c b/dlls/msvcp90/locale.c index 192ee8b98ef..069251661aa 100644 --- a/dlls/msvcp90/locale.c +++ b/dlls/msvcp90/locale.c @@ -4006,46 +4006,51 @@ void __thiscall codecvt_char16__Init(codecvt_char16 *this, const _Locinfo *locin FIXME("(%p %p) stub\n", this, locinfo); } +/* ??0?$codecvt(a)_SDU_Mbstatet@@@std@@QAA(a)ABV_Locinfo@1(a)KW4_Codecvt_mode@1(a)I@Z */ +/* ??0?$codecvt(a)_SDU_Mbstatet@@@std@@QAE(a)ABV_Locinfo@1(a)KW4_Codecvt_mode@1(a)I@Z */ +/* ??0?$codecvt(a)_SDU_Mbstatet@@@std@@QEAA(a)AEBV_Locinfo@1(a)KW4_Codecvt_mode@1(a)_K@Z */ +DEFINE_THISCALL_WRAPPER(codecvt_char16_ctor_mode, 16) +codecvt_char16* __thiscall codecvt_char16_ctor_mode(codecvt_char16 *this, const _Locinfo *locinfo, + ULONG max_code, codecvt_convert_mode mode, unsigned int refs) +{ + TRACE("(%p %ld %d %u)\n", this, max_code, mode, refs); + + codecvt_base_ctor_refs(&this->base, refs); + this->base.facet.vtable = &codecvt_char16_vtable; + this->convert_mode = mode; + this->max_code = max_code; + return this; +} + /* ??0?$codecvt(a)_SDU_Mbstatet@@@std@@QAA(a)ABV_Locinfo@1(a)I@Z */ /* ??0?$codecvt(a)_SDU_Mbstatet@@@std@@QAE(a)ABV_Locinfo@1(a)I@Z */ /* ??0?$codecvt(a)_SDU_Mbstatet@@@std@@QEAA(a)AEBV_Locinfo@1(a)_K@Z */ DEFINE_THISCALL_WRAPPER(codecvt_char16_ctor_locinfo, 12) codecvt_char16* __thiscall codecvt_char16_ctor_locinfo(codecvt_char16 *this, - const _Locinfo *locinfo, size_t refs) + const _Locinfo *locinfo, unsigned int refs) { - FIXME("(%p %p %Iu) stub\n", this, locinfo, refs); - return NULL; + TRACE("(%p %p %u)\n", this, locinfo, refs); + return codecvt_char16_ctor_mode(this, locinfo, MAX_UCSCHAR, consume_header, refs); } /* ??0?$codecvt(a)_SDU_Mbstatet@@@std@@QAA(a)I@Z */ /* ??0?$codecvt(a)_SDU_Mbstatet@@@std@@QAE(a)I@Z */ /* ??0?$codecvt(a)_SDU_Mbstatet@@@std@@QEAA(a)_K@Z */ DEFINE_THISCALL_WRAPPER(codecvt_char16_ctor_refs, 8) -codecvt_char* __thiscall codecvt_char16_ctor_refs(codecvt_char16 *this, size_t refs) -{ - FIXME("(%p %Iu) stub\n", this, refs); - return NULL; -} - -/* ??0?$codecvt(a)_SDU_Mbstatet@@@std@@QAA(a)ABV_Locinfo@1(a)KW4_Codecvt_mode@1(a)I@Z */ -/* ??0?$codecvt(a)_SDU_Mbstatet@@@std@@QAE(a)ABV_Locinfo@1(a)KW4_Codecvt_mode@1(a)I@Z */ -/* ??0?$codecvt(a)_SDU_Mbstatet@@@std@@QEAA(a)AEBV_Locinfo@1(a)KW4_Codecvt_mode@1(a)_K@Z */ -DEFINE_THISCALL_WRAPPER(codecvt_char16_ctor_mode, 16) -codecvt_char16* __thiscall codecvt_char16_ctor_mode(codecvt_char16 *this, - ULONG max_code, codecvt_convert_mode mode, size_t refs) +codecvt_char16* __thiscall codecvt_char16_ctor_refs(codecvt_char16 *this, unsigned int refs) { - FIXME("(%p %ld %d %Iu) stub\n", this, max_code, mode, refs); - return NULL; + TRACE("(%p %u)\n", this, refs); + return codecvt_char16_ctor_locinfo(this, NULL, refs); } /* ??_F?$codecvt(a)_SDU_Mbstatet@@@std@@QAAXXZ */ /* ??_F?$codecvt(a)_SDU_Mbstatet@@@std@@QAEXXZ */ /* ??_F?$codecvt(a)_SDU_Mbstatet@@@std@@QEAAXXZ */ DEFINE_THISCALL_WRAPPER(codecvt_char16_ctor, 4) -codecvt_char* __thiscall codecvt_char16_ctor(codecvt_char16 *this) +codecvt_char16* __thiscall codecvt_char16_ctor(codecvt_char16 *this) { - FIXME("(%p) stub\n", this); - return NULL; + TRACE("(%p)\n", this); + return codecvt_char16_ctor_refs(this, 0); } /* ??1?$codecvt(a)_SDU_Mbstatet@@@std@@MAA(a)XZ */ @@ -4054,7 +4059,8 @@ codecvt_char* __thiscall codecvt_char16_ctor(codecvt_char16 *this) DEFINE_THISCALL_WRAPPER(codecvt_char16_dtor, 4) void __thiscall codecvt_char16_dtor(codecvt_char16 *this) { - FIXME("(%p) stub\n", this); + TRACE("(%p)\n", this); + codecvt_base_dtor(&this->base); } DEFINE_THISCALL_WRAPPER(codecvt_char16_vector_dtor, 8) diff --git a/dlls/msvcp90/msvcp90.h b/dlls/msvcp90/msvcp90.h index b6e20826ff7..1994b49473b 100644 --- a/dlls/msvcp90/msvcp90.h +++ b/dlls/msvcp90/msvcp90.h @@ -248,6 +248,8 @@ typedef enum convert_mode /* class codecvt<char16> */ typedef struct { codecvt_base base; + unsigned int max_code; + codecvt_convert_mode convert_mode; } codecvt_char16; /* class codecvt<char32> */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/7707