Nikolay Sivov : msvcrt: Added _wcslwr_s implementation.

Alexandre Julliard julliard at winehq.org
Mon Mar 7 12:22:45 CST 2011


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Sat Mar  5 01:59:08 2011 +0300

msvcrt: Added _wcslwr_s implementation.

---

 dlls/msvcr100/msvcr100.spec |    2 +-
 dlls/msvcr80/msvcr80.spec   |    2 +-
 dlls/msvcr90/msvcr90.spec   |    2 +-
 dlls/msvcrt/msvcrt.spec     |    2 +-
 dlls/msvcrt/tests/string.c  |   90 +++++++++++++++++++++++++++++++++++++++++++
 dlls/msvcrt/wcs.c           |   28 +++++++++++++
 6 files changed, 122 insertions(+), 4 deletions(-)

diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec
index 608bfc6..42d8310 100644
--- a/dlls/msvcr100/msvcr100.spec
+++ b/dlls/msvcr100/msvcr100.spec
@@ -1293,7 +1293,7 @@
 @ stub _wcsicoll_l
 @ cdecl _wcslwr(wstr) msvcrt._wcslwr
 @ stub _wcslwr_l
-@ stub _wcslwr_s
+@ cdecl _wcslwr_s(wstr long) msvcrt._wcslwr_s
 @ stub _wcslwr_s_l
 @ stub _wcsncoll
 @ stub _wcsncoll_l
diff --git a/dlls/msvcr80/msvcr80.spec b/dlls/msvcr80/msvcr80.spec
index 58b855c..f9eaaf0 100644
--- a/dlls/msvcr80/msvcr80.spec
+++ b/dlls/msvcr80/msvcr80.spec
@@ -1146,7 +1146,7 @@
 @ stub _wcsicoll_l
 @ cdecl _wcslwr(wstr) msvcrt._wcslwr
 @ stub _wcslwr_l
-@ stub _wcslwr_s
+@ cdecl _wcslwr_s(wstr long) msvcrt._wcslwr_s
 @ stub _wcslwr_s_l
 @ stub _wcsncoll
 @ stub _wcsncoll_l
diff --git a/dlls/msvcr90/msvcr90.spec b/dlls/msvcr90/msvcr90.spec
index d76acc8..b7288da 100644
--- a/dlls/msvcr90/msvcr90.spec
+++ b/dlls/msvcr90/msvcr90.spec
@@ -1133,7 +1133,7 @@
 @ stub _wcsicoll_l
 @ cdecl _wcslwr(wstr) msvcrt._wcslwr
 @ stub _wcslwr_l
-@ stub _wcslwr_s
+@ cdecl _wcslwr_s(wstr long) msvcrt._wcslwr_s
 @ stub _wcslwr_s_l
 @ stub _wcsncoll
 @ stub _wcsncoll_l
diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec
index c7f2120..f75c0d9 100644
--- a/dlls/msvcrt/msvcrt.spec
+++ b/dlls/msvcrt/msvcrt.spec
@@ -1067,7 +1067,7 @@
 # stub _wcsicoll_l
 @ cdecl _wcslwr(wstr) ntdll._wcslwr
 # stub _wcslwr_l
-# stub _wcslwr_s
+@ cdecl _wcslwr_s(wstr long) MSVCRT__wcslwr_s
 # stub _wcslwr_s_l
 @ stub _wcsncoll #(wstr wstr long)
 # stub _wcsncoll_l
diff --git a/dlls/msvcrt/tests/string.c b/dlls/msvcrt/tests/string.c
index c532fce..dfa38e6 100644
--- a/dlls/msvcrt/tests/string.c
+++ b/dlls/msvcrt/tests/string.c
@@ -75,6 +75,7 @@ static errno_t (__cdecl *p_ultoa_s)(__msvcrt_ulong,char*,size_t,int);
 static int *p__mb_cur_max;
 static unsigned char *p_mbctype;
 static _invalid_parameter_handler (__cdecl *p_set_invalid_parameter_handler)(_invalid_parameter_handler);
+static int (__cdecl *p_wcslwr_s)(wchar_t*,size_t);
 
 #define SETNOFAIL(x,y) x = (void*)GetProcAddress(hMsvcrt,y)
 #define SET(x,y) SETNOFAIL(x,y); ok(x != NULL, "Export '%s' not found\n", y)
@@ -731,6 +732,93 @@ static void test__wcsupr_s(void)
     ok(!wcscmp(testBuffer, expectedString), "Expected the string to be fully upper-case\n");
 }
 
+static void test__wcslwr_s(void)
+{
+    static const WCHAR mixedString[] = {'M', 'i', 'X', 'e', 'D', 'l', 'o', 'w',
+                                        'e', 'r', 'U', 'P', 'P', 'E', 'R', 0};
+    static const WCHAR expectedString[] = {'m', 'i', 'x', 'e', 'd', 'l', 'o',
+                                           'w', 'e', 'r', 'u', 'p', 'p', 'e',
+                                           'r', 0};
+    WCHAR buffer[2*sizeof(mixedString)/sizeof(WCHAR)];
+    int ret;
+
+    if (!p_wcslwr_s)
+    {
+        win_skip("_wcslwr_s not found\n");
+        return;
+    }
+
+    /* Test NULL input string and invalid size. */
+    errno = EBADF;
+    ret = p_wcslwr_s(NULL, 0);
+    ok(ret == EINVAL, "expected EINVAL, got %d\n", ret);
+    ok(errno == EINVAL, "expected errno EINVAL, got %d\n", errno);
+
+    /* Test NULL input string and valid size. */
+    errno = EBADF;
+    ret = p_wcslwr_s(NULL, sizeof(buffer)/sizeof(wchar_t));
+    ok(ret == EINVAL, "expected EINVAL, got %d\n", ret);
+    ok(errno == EINVAL, "expected errno EINVAL, got %d\n", errno);
+
+    /* Test empty string with zero size. */
+    errno = EBADF;
+    buffer[0] = 'a';
+    ret = p_wcslwr_s(buffer, 0);
+    ok(ret == EINVAL, "expected EINVAL, got %d\n", ret);
+    ok(errno == EINVAL, "expected errno EINVAL, got %d\n", errno);
+    ok(buffer[0] == 0, "expected empty string\n");
+
+    /* Test empty string with size of one. */
+    buffer[0] = 0;
+    ret = p_wcslwr_s(buffer, 1);
+    ok(ret == 0, "got %d\n", ret);
+    ok(buffer[0] == 0, "expected buffer to be unchanged\n");
+
+    /* Test one-byte buffer with zero size. */
+    errno = EBADF;
+    buffer[0] = 'x';
+    ret = p_wcslwr_s(buffer, 0);
+    ok(ret == EINVAL, "expected EINVAL, got %d\n", ret);
+    ok(errno == EINVAL, "expected errno to be EINVAL, got %d\n", errno);
+    ok(buffer[0] == '\0', "expected empty string\n");
+
+    /* Test one-byte buffer with size of one. */
+    errno = EBADF;
+    buffer[0] = 'x';
+    ret = p_wcslwr_s(buffer, 1);
+    ok(ret == EINVAL, "expected EINVAL, got %d\n", ret);
+    ok(errno == EINVAL, "expected errno to be EINVAL, got %d\n", errno);
+    ok(buffer[0] == '\0', "expected empty string\n");
+
+    /* Test invalid size. */
+    wcscpy(buffer, mixedString);
+    errno = EBADF;
+    ret = p_wcslwr_s(buffer, 0);
+    ok(ret == EINVAL, "Expected EINVAL, got %d\n", ret);
+    ok(errno == EINVAL, "expected errno to be EINVAL, got %d\n", errno);
+    ok(buffer[0] == '\0', "expected empty string\n");
+
+    /* Test normal string uppercasing. */
+    wcscpy(buffer, mixedString);
+    ret = p_wcslwr_s(buffer, sizeof(mixedString)/sizeof(WCHAR));
+    ok(ret == 0, "expected 0, got %d\n", ret);
+    ok(!wcscmp(buffer, expectedString), "expected lowercase\n");
+
+    /* Test uppercasing with a shorter buffer size count. */
+    wcscpy(buffer, mixedString);
+    errno = EBADF;
+    ret = p_wcslwr_s(buffer, sizeof(mixedString)/sizeof(WCHAR) - 1);
+    ok(ret == EINVAL, "expected EINVAL, got %d\n", ret);
+    ok(errno == EINVAL, "expected errno to be EINVAL, got %d\n", errno);
+    ok(buffer[0] == '\0', "expected empty string\n");
+
+    /* Test uppercasing with a longer buffer size count. */
+    wcscpy(buffer, mixedString);
+    ret = p_wcslwr_s(buffer, sizeof(buffer)/sizeof(WCHAR));
+    ok(ret == 0, "expected 0, got %d\n", ret);
+    ok(!wcscmp(buffer, expectedString), "expected lowercase\n");
+}
+
 static void test_mbcjisjms(void)
 {
     /* List of value-pairs to test. The test assumes the last pair to be {0, ..} */
@@ -1732,6 +1820,7 @@ START_TEST(string)
     p_strlwr_s = (void *)GetProcAddress(hMsvcrt, "_strlwr_s");
     p_ultoa_s = (void *)GetProcAddress(hMsvcrt, "_ultoa_s");
     p_set_invalid_parameter_handler = (void *) GetProcAddress(hMsvcrt, "_set_invalid_parameter_handler");
+    p_wcslwr_s = (void*)GetProcAddress(hMsvcrt, "_wcslwr_s");
 
     /* MSVCRT memcpy behaves like memmove for overlapping moves,
        MFC42 CString::Insert seems to rely on that behaviour */
@@ -1771,4 +1860,5 @@ START_TEST(string)
     test_wcsncat_s();
     test__mbsnbcat_s();
     test__ultoa_s();
+    test__wcslwr_s();
 }
diff --git a/dlls/msvcrt/wcs.c b/dlls/msvcrt/wcs.c
index b01e60b..d45094a 100644
--- a/dlls/msvcrt/wcs.c
+++ b/dlls/msvcrt/wcs.c
@@ -131,6 +131,34 @@ INT CDECL MSVCRT__wcsupr_s( MSVCRT_wchar_t* str, MSVCRT_size_t n )
   return MSVCRT_EINVAL;
 }
 
+/******************************************************************
+ *		_wcslwr_s (MSVCRT.@)
+ */
+int CDECL MSVCRT__wcslwr_s( MSVCRT_wchar_t* str, MSVCRT_size_t n )
+{
+  MSVCRT_wchar_t* ptr = str;
+
+  if (!str || !n)
+  {
+    if (str) *str = '\0';
+    *MSVCRT__errno() = MSVCRT_EINVAL;
+    return MSVCRT_EINVAL;
+  }
+
+  while (n--)
+  {
+    if (!*ptr) return 0;
+    *ptr = tolowerW(*ptr);
+    ptr++;
+  }
+
+  /* MSDN claims that the function should return and set errno to
+   * ERANGE, which doesn't seem to be true based on the tests. */
+  *str = '\0';
+  *MSVCRT__errno() = MSVCRT_EINVAL;
+  return MSVCRT_EINVAL;
+}
+
 /*********************************************************************
  * _wcstod_l - not exported in native msvcrt
  */




More information about the wine-cvs mailing list