Module: wine Branch: master Commit: cf2073144782a46c727837482ca4681727226606 URL: http://source.winehq.org/git/wine.git/?a=commit;h=cf2073144782a46c727837482c...
Author: Piotr Caban piotr@codeweavers.com Date: Mon Jul 6 19:40:10 2015 +0200
msvcrt: Add _mbscat_s_l implementation.
---
dlls/msvcr100/msvcr100.spec | 4 +-- dlls/msvcr110/msvcr110.spec | 4 +-- dlls/msvcr120/msvcr120.spec | 4 +-- dlls/msvcr80/msvcr80.spec | 4 +-- dlls/msvcr90/msvcr90.spec | 4 +-- dlls/msvcrt/mbcs.c | 50 +++++++++++++++++++++++++++ dlls/msvcrt/msvcrt.h | 1 + dlls/msvcrt/msvcrt.spec | 4 +-- dlls/msvcrt/tests/string.c | 83 +++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 146 insertions(+), 12 deletions(-)
diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec index 986e372..f9eae91 100644 --- a/dlls/msvcr100/msvcr100.spec +++ b/dlls/msvcr100/msvcr100.spec @@ -1096,8 +1096,8 @@ @ stub _mblen_l @ cdecl _mbsbtype(str long) @ stub _mbsbtype_l -@ stub _mbscat_s -@ stub _mbscat_s_l +@ cdecl _mbscat_s(ptr long str) +@ cdecl _mbscat_s_l(ptr long str ptr) @ cdecl _mbschr(str long) @ stub _mbschr_l @ cdecl _mbscmp(str str) diff --git a/dlls/msvcr110/msvcr110.spec b/dlls/msvcr110/msvcr110.spec index 78131aa..3faca07 100644 --- a/dlls/msvcr110/msvcr110.spec +++ b/dlls/msvcr110/msvcr110.spec @@ -1454,8 +1454,8 @@ @ stub _mblen_l @ cdecl _mbsbtype(str long) @ stub _mbsbtype_l -@ stub _mbscat_s -@ stub _mbscat_s_l +@ cdecl _mbscat_s(ptr long str) +@ cdecl _mbscat_s_l(ptr long str ptr) @ cdecl _mbschr(str long) @ stub _mbschr_l @ cdecl _mbscmp(str str) diff --git a/dlls/msvcr120/msvcr120.spec b/dlls/msvcr120/msvcr120.spec index 9fb8d93..5077a67 100644 --- a/dlls/msvcr120/msvcr120.spec +++ b/dlls/msvcr120/msvcr120.spec @@ -1462,8 +1462,8 @@ @ stub _mblen_l @ cdecl _mbsbtype(str long) @ stub _mbsbtype_l -@ stub _mbscat_s -@ stub _mbscat_s_l +@ cdecl _mbscat_s(ptr long str) +@ cdecl _mbscat_s_l(ptr long str ptr) @ cdecl _mbschr(str long) @ stub _mbschr_l @ cdecl _mbscmp(str str) diff --git a/dlls/msvcr80/msvcr80.spec b/dlls/msvcr80/msvcr80.spec index ef24b91..fac2446 100644 --- a/dlls/msvcr80/msvcr80.spec +++ b/dlls/msvcr80/msvcr80.spec @@ -769,8 +769,8 @@ @ stub _mblen_l @ cdecl _mbsbtype(str long) @ stub _mbsbtype_l -@ stub _mbscat_s -@ stub _mbscat_s_l +@ cdecl _mbscat_s(ptr long str) +@ cdecl _mbscat_s_l(ptr long str ptr) @ cdecl _mbschr(str long) @ stub _mbschr_l @ cdecl _mbscmp(str str) diff --git a/dlls/msvcr90/msvcr90.spec b/dlls/msvcr90/msvcr90.spec index e58b8f9..479b88b 100644 --- a/dlls/msvcr90/msvcr90.spec +++ b/dlls/msvcr90/msvcr90.spec @@ -746,8 +746,8 @@ @ stub _mblen_l @ cdecl _mbsbtype(str long) @ stub _mbsbtype_l -@ stub _mbscat_s -@ stub _mbscat_s_l +@ cdecl _mbscat_s(ptr long str) +@ cdecl _mbscat_s_l(ptr long str ptr) @ cdecl _mbschr(str long) @ stub _mbschr_l @ cdecl _mbscmp(str str) diff --git a/dlls/msvcrt/mbcs.c b/dlls/msvcrt/mbcs.c index 8c4bc02..240ec2c 100644 --- a/dlls/msvcrt/mbcs.c +++ b/dlls/msvcrt/mbcs.c @@ -1053,6 +1053,56 @@ unsigned char * CDECL _mbscat( unsigned char *dst, const unsigned char *src ) }
/********************************************************************* + * _mbscat_s_l (MSVCRT.@) + */ +int CDECL _mbscat_s_l( unsigned char *dst, MSVCRT_size_t size, + const unsigned char *src, MSVCRT__locale_t locale ) +{ + MSVCRT_size_t i, j; + int ret = 0; + + if(!MSVCRT_CHECK_PMT(dst != NULL)) return MSVCRT_EINVAL; + if(!MSVCRT_CHECK_PMT(src != NULL)) return MSVCRT_EINVAL; + + for(i=0; i<size; i++) + if(!dst[i]) break; + if(i == size) { + MSVCRT_INVALID_PMT("dst is not NULL-terminated", MSVCRT_EINVAL); + if(size) dst[0] = 0; + return MSVCRT_EINVAL; + } + + if(i && _ismbblead_l(dst[i-1], locale)) { + ret = MSVCRT_EILSEQ; + i--; + } + + for(j=0; src[j] && i+j<size; j++) + dst[i+j] = src[j]; + if(i+j == size) { + MSVCRT_INVALID_PMT("dst buffer is to small", MSVCRT_ERANGE); + dst[0] = 0; + return MSVCRT_ERANGE; + } + + if(j && _ismbblead_l(src[j-1], locale)) { + ret = MSVCRT_EILSEQ; + j--; + } + + dst[i+j] = 0; + return ret; +} + +/********************************************************************* + * _mbscat_s (MSVCRT.@) + */ +int CDECL _mbscat_s( unsigned char *dst, MSVCRT_size_t size, const unsigned char *src ) +{ + return _mbscat_s_l(dst, size, src, NULL); +} + +/********************************************************************* * _mbscpy (MSVCRT.@) */ unsigned char* CDECL _mbscpy( unsigned char *dst, const unsigned char *src ) diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h index 19f3c10..88f35b3 100644 --- a/dlls/msvcrt/msvcrt.h +++ b/dlls/msvcrt/msvcrt.h @@ -1009,6 +1009,7 @@ int _setmbcp_l(int, LCID, MSVCRT_pthreadmbcinfo) DECLSPEC_HIDDEN; int __cdecl MSVCRT__write(int,const void*,unsigned int); int __cdecl _getch(void); int __cdecl _ismbblead(unsigned int); +int __cdecl _ismbblead_l(unsigned int, MSVCRT__locale_t); int __cdecl _ismbclegal(unsigned int c); int __cdecl _ismbstrail(const unsigned char* start, const unsigned char* str); int __cdecl MSVCRT_mbtowc(MSVCRT_wchar_t*,const char*,MSVCRT_size_t); diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec index 7fb13a6..37b94e3 100644 --- a/dlls/msvcrt/msvcrt.spec +++ b/dlls/msvcrt/msvcrt.spec @@ -713,8 +713,8 @@ @ cdecl _mbsbtype(str long) # stub _mbsbtype_l(str long ptr) @ cdecl _mbscat(str str) -# stub _mbscat_s(str long str) -# stub _mbscat_s_l(str long str ptr) +@ cdecl _mbscat_s(ptr long str) +@ cdecl _mbscat_s_l(ptr long str ptr) @ cdecl _mbschr(str long) # stub _mbschr_l(str long ptr) @ cdecl _mbscmp(str str) diff --git a/dlls/msvcrt/tests/string.c b/dlls/msvcrt/tests/string.c index 5768c0f..476f762 100644 --- a/dlls/msvcrt/tests/string.c +++ b/dlls/msvcrt/tests/string.c @@ -58,6 +58,7 @@ static int (__cdecl *p_memmove_s)(void *, size_t, const void *, size_t); static int* (__cdecl *pmemcmp)(void *, const void *, size_t n); static int (__cdecl *pstrcpy_s)(char *dst, size_t len, const char *src); static int (__cdecl *pstrcat_s)(char *dst, size_t len, const char *src); +static int (__cdecl *p_mbscat_s)(unsigned char *dst, size_t size, const unsigned char *src); static int (__cdecl *p_mbsnbcat_s)(unsigned char *dst, size_t size, const unsigned char *src, size_t count); static int (__cdecl *p_mbsnbcpy_s)(unsigned char * dst, size_t size, const unsigned char * src, size_t count); static int (__cdecl *p__mbscpy_s)(unsigned char*, size_t, const unsigned char*); @@ -732,6 +733,86 @@ static void test_strcat_s(void) ok(ret == EINVAL, "strcat_s: Writing to a NULL string returned %d, expected EINVAL\n", ret); }
+static void test__mbscat_s(void) +{ + unsigned char dst[8], src[4]; + int err; + int prev_cp = _getmbcp(); + + if(!p_mbscat_s) + { + win_skip("_mbscat_s not found\n"); + return; + } + + + src[0] = dst[0] = 0; + err = p_mbscat_s(NULL, sizeof(dst), src); + ok(err == EINVAL, "_mbscat_s returned %d\n", err); + + err = p_mbscat_s(dst, sizeof(dst), NULL); + ok(err == EINVAL, "_mbscat_s returned %d\n", err); + + dst[0] = 'a'; + err = p_mbscat_s(dst, 1, src); + ok(err == EINVAL, "_mbscat_s returned %d\n", err); + + memset(dst, 'a', sizeof(dst)); + dst[6] = 0; + src[0] = 'b'; + src[1] = 0; + + err = p_mbscat_s(dst, sizeof(dst), src); + ok(err == 0, "_mbscat_s returned %d\n", err); + ok(!memcmp(dst, "aaaaaab", 8), "dst = %s\n", dst); + + err = p_mbscat_s(dst, sizeof(dst), src); + ok(err == ERANGE, "_mbscat_s returned %d\n", err); + ok(!dst[0], "dst[0] = %c\n", dst[0]); + ok(dst[1] == 'a', "dst[1] = %c\n", dst[1]); + + _setmbcp(932); + /* test invalid str in dst */ + dst[0] = 0x81; + dst[1] = 0x81; + dst[2] = 0x52; + dst[3] = 0; + src[0] = 'a'; + src[1] = 0; + err = p_mbscat_s(dst, sizeof(dst), src); + ok(err == 0, "_mbscat_s returned %d\n", err); + + /* test invalid str in src */ + dst[0] = 0; + src[0] = 0x81; + src[1] = 0x81; + src[2] = 0x52; + src[3] = 0; + err = p_mbscat_s(dst, sizeof(dst), src); + ok(err == 0, "_mbscat_s returned %d\n", err); + + /* test dst with leading byte on the end of buffer */ + dst[0] = 'a'; + dst[1] = 0x81; + dst[2] = 0; + src[0] = 'R'; + src[1] = 0; + err = p_mbscat_s(dst, sizeof(dst), src); + ok(err == EILSEQ, "_mbscat_s returned %d\n", err); + ok(!memcmp(dst, "aR", 3), "dst = %s\n", dst); + + /* test src with leading byte on the end of buffer */ + dst[0] = 'a'; + dst[1] = 0; + src[0] = 'b'; + src[1] = 0x81; + src[2] = 0; + err = p_mbscat_s(dst, sizeof(dst), src); + ok(err == EILSEQ, "_mbscat_s returned %d\n", err); + ok(!memcmp(dst, "ab", 3), "dst = %s\n", dst); + _setmbcp(prev_cp); +} + static void test__mbsnbcpy_s(void) { unsigned char dest[8]; @@ -2984,6 +3065,7 @@ START_TEST(string) SET(p__mb_cur_max,"__mb_cur_max"); pstrcpy_s = (void *)GetProcAddress( hMsvcrt,"strcpy_s" ); pstrcat_s = (void *)GetProcAddress( hMsvcrt,"strcat_s" ); + p_mbscat_s = (void*)GetProcAddress( hMsvcrt, "_mbscat_s" ); p_mbsnbcat_s = (void *)GetProcAddress( hMsvcrt,"_mbsnbcat_s" ); p_mbsnbcpy_s = (void *)GetProcAddress( hMsvcrt,"_mbsnbcpy_s" ); p__mbscpy_s = (void *)GetProcAddress( hMsvcrt,"_mbscpy_s" ); @@ -3037,6 +3119,7 @@ START_TEST(string) test_memcpy_s(); test_memmove_s(); test_strcat_s(); + test__mbscat_s(); test__mbsnbcpy_s(); test__mbscpy_s(); test_mbcjisjms();