Andrew Nguyen : msvcrt: Implement strerror_s.

Alexandre Julliard julliard at winehq.org
Tue Sep 28 11:13:34 CDT 2010


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

Author: Andrew Nguyen <anguyen at codeweavers.com>
Date:   Tue Sep 28 03:48:13 2010 -0500

msvcrt: Implement strerror_s.

---

 dlls/msvcr100/msvcr100.spec |    2 +-
 dlls/msvcr80/msvcr80.spec   |    2 +-
 dlls/msvcr90/msvcr90.spec   |    2 +-
 dlls/msvcrt/errno.c         |   27 +++++++++++++++++++++++
 dlls/msvcrt/msvcrt.spec     |    2 +-
 dlls/msvcrt/tests/misc.c    |   50 +++++++++++++++++++++++++++++++++++++++++++
 include/msvcrt/string.h     |    1 +
 7 files changed, 82 insertions(+), 4 deletions(-)

diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec
index 5590d47..6d90b3b 100644
--- a/dlls/msvcr100/msvcr100.spec
+++ b/dlls/msvcr100/msvcr100.spec
@@ -1581,7 +1581,7 @@
 @ cdecl strcpy_s(ptr long str) msvcrt.strcpy_s
 @ cdecl strcspn(str str) msvcrt.strcspn
 @ cdecl strerror(long) msvcrt.strerror
-@ stub strerror_s
+@ cdecl strerror_s(ptr long long) msvcrt.strerror_s
 @ cdecl strftime(str long str ptr) msvcrt.strftime
 @ cdecl strlen(str) msvcrt.strlen
 @ cdecl strncat(str str long) msvcrt.strncat
diff --git a/dlls/msvcr80/msvcr80.spec b/dlls/msvcr80/msvcr80.spec
index 8f547cf..c30ef6e 100644
--- a/dlls/msvcr80/msvcr80.spec
+++ b/dlls/msvcr80/msvcr80.spec
@@ -1435,7 +1435,7 @@
 @ cdecl strcpy_s(ptr long str) msvcrt.strcpy_s
 @ cdecl strcspn(str str) msvcrt.strcspn
 @ cdecl strerror(long) msvcrt.strerror
-@ stub strerror_s
+@ cdecl strerror_s(ptr long long) msvcrt.strerror_s
 @ cdecl strftime(str long str ptr) msvcrt.strftime
 @ cdecl strlen(str) msvcrt.strlen
 @ cdecl strncat(str str long) msvcrt.strncat
diff --git a/dlls/msvcr90/msvcr90.spec b/dlls/msvcr90/msvcr90.spec
index 01df496..4e07480 100644
--- a/dlls/msvcr90/msvcr90.spec
+++ b/dlls/msvcr90/msvcr90.spec
@@ -1419,7 +1419,7 @@
 @ cdecl strcpy_s(ptr long str) msvcrt.strcpy_s
 @ cdecl strcspn(str str) msvcrt.strcspn
 @ cdecl strerror(long) msvcrt.strerror
-@ stub strerror_s
+@ cdecl strerror_s(ptr long long) msvcrt.strerror_s
 @ cdecl strftime(str long str ptr) msvcrt.strftime
 @ cdecl strlen(str) msvcrt.strlen
 @ cdecl strncat(str str long) msvcrt.strncat
diff --git a/dlls/msvcrt/errno.c b/dlls/msvcrt/errno.c
index 4d97051..2e03ec1 100644
--- a/dlls/msvcrt/errno.c
+++ b/dlls/msvcrt/errno.c
@@ -219,6 +219,33 @@ char* CDECL MSVCRT_strerror(int err)
 }
 
 /**********************************************************************
+ *		strerror_s	(MSVCRT.@)
+ */
+int CDECL strerror_s(char *buffer, MSVCRT_size_t numberOfElements, int errnum)
+{
+    char *ptr;
+
+    if (!buffer || !numberOfElements)
+    {
+        *MSVCRT__errno() = MSVCRT_EINVAL;
+        return MSVCRT_EINVAL;
+    }
+
+    if (errnum < 0 || errnum > MSVCRT__sys_nerr)
+        errnum = MSVCRT__sys_nerr;
+
+    ptr = MSVCRT__sys_errlist[errnum];
+    while (*ptr && numberOfElements > 1)
+    {
+        *buffer++ = *ptr++;
+        numberOfElements--;
+    }
+
+    *buffer = '\0';
+    return 0;
+}
+
+/**********************************************************************
  *		_strerror	(MSVCRT.@)
  */
 char* CDECL _strerror(const char* str)
diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec
index ccd3c6a..4fb9f8d 100644
--- a/dlls/msvcrt/msvcrt.spec
+++ b/dlls/msvcrt/msvcrt.spec
@@ -1374,7 +1374,7 @@
 @ cdecl strcpy_s(ptr long str) MSVCRT_strcpy_s
 @ cdecl strcspn(str str) ntdll.strcspn
 @ cdecl strerror(long) MSVCRT_strerror
-# stub strerror_s
+@ cdecl strerror_s(ptr long long)
 @ cdecl strftime(str long str ptr) MSVCRT_strftime
 @ cdecl strlen(str) ntdll.strlen
 @ cdecl strncat(str str long) ntdll.strncat
diff --git a/dlls/msvcrt/tests/misc.c b/dlls/msvcrt/tests/misc.c
index 0e45eba..34980eb 100644
--- a/dlls/msvcrt/tests/misc.c
+++ b/dlls/msvcrt/tests/misc.c
@@ -25,6 +25,7 @@
 static int (__cdecl *prand_s)(unsigned int *);
 static int (__cdecl *pmemcpy_s)(void *, MSVCRT_size_t, void*, MSVCRT_size_t);
 static int (__cdecl *pI10_OUTPUT)(long double, int, int, void*);
+static int (__cdecl *pstrerror_s)(char *, MSVCRT_size_t, int);
 
 static void init(void)
 {
@@ -33,6 +34,7 @@ static void init(void)
     prand_s = (void *)GetProcAddress(hmod, "rand_s");
     pmemcpy_s = (void*)GetProcAddress(hmod, "memcpy_s");
     pI10_OUTPUT = (void*)GetProcAddress(hmod, "$I10_OUTPUT");
+    pstrerror_s = (void *)GetProcAddress(hmod, "strerror_s");
 }
 
 static void test_rand_s(void)
@@ -192,6 +194,53 @@ static void test_I10_OUTPUT(void)
     }
 }
 
+static void test_strerror_s(void)
+{
+    int ret;
+    char buf[256];
+
+    if (!pstrerror_s)
+    {
+        win_skip("strerror_s is not available\n");
+        return;
+    }
+
+    errno = EBADF;
+    ret = pstrerror_s(NULL, 0, 0);
+    ok(ret == EINVAL, "Expected strerror_s to return EINVAL, got %d\n", ret);
+    ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
+
+    errno = EBADF;
+    ret = pstrerror_s(NULL, sizeof(buf), 0);
+    ok(ret == EINVAL, "Expected strerror_s to return EINVAL, got %d\n", ret);
+    ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
+
+    memset(buf, 'X', sizeof(buf));
+    errno = EBADF;
+    ret = pstrerror_s(buf, 0, 0);
+    ok(ret == EINVAL, "Expected strerror_s to return EINVAL, got %d\n", ret);
+    ok(errno == EINVAL, "Expected errno to be EINVAL, got %d\n", errno);
+    ok(buf[0] == 'X', "Expected output buffer to be untouched\n");
+
+    memset(buf, 'X', sizeof(buf));
+    ret = pstrerror_s(buf, 1, 0);
+    ok(ret == 0, "Expected strerror_s to return 0, got %d\n", ret);
+    ok(strlen(buf) == 0, "Expected output buffer to be null terminated\n");
+
+    memset(buf, 'X', sizeof(buf));
+    ret = pstrerror_s(buf, 2, 0);
+    ok(ret == 0, "Expected strerror_s to return 0, got %d\n", ret);
+    ok(strlen(buf) == 1, "Expected output buffer to be truncated\n");
+
+    memset(buf, 'X', sizeof(buf));
+    ret = pstrerror_s(buf, sizeof(buf), 0);
+    ok(ret == 0, "Expected strerror_s to return 0, got %d\n", ret);
+
+    memset(buf, 'X', sizeof(buf));
+    ret = pstrerror_s(buf, sizeof(buf), -1);
+    ok(ret == 0, "Expected strerror_s to return 0, got %d\n", ret);
+}
+
 START_TEST(misc)
 {
     init();
@@ -199,4 +248,5 @@ START_TEST(misc)
     test_rand_s();
     test_memcpy_s();
     test_I10_OUTPUT();
+    test_strerror_s();
 }
diff --git a/include/msvcrt/string.h b/include/msvcrt/string.h
index 3e60a4d..614fa85 100644
--- a/include/msvcrt/string.h
+++ b/include/msvcrt/string.h
@@ -44,6 +44,7 @@ static inline void* memccpy(void *s1, const void *s2, int c, size_t n) { return
 int   __cdecl _strcmpi(const char*,const char*);
 char* __cdecl _strdup(const char*);
 char* __cdecl _strerror(const char*);
+errno_t __cdecl strerror_s(char*,size_t,int);
 int   __cdecl _stricmp(const char*,const char*);
 int   __cdecl _stricoll(const char*,const char*);
 char* __cdecl _strlwr(char*);




More information about the wine-cvs mailing list