Piotr Caban : msvcrt: Add _mbscat_s_l implementation.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Jul 7 08:11:58 CDT 2015


Module: wine
Branch: master
Commit: cf2073144782a46c727837482ca4681727226606
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=cf2073144782a46c727837482ca4681727226606

Author: Piotr Caban <piotr at 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();




More information about the wine-cvs mailing list