[PATCH] [Msvcrt]: fixing errno handling in strtol and strtoul (#18151)

Eric Pouech eric.pouech at orange.fr
Sat Aug 29 15:35:33 CDT 2009




A+
---

 dlls/msvcrt/errno.c        |   63 ++++++++++++++++++++++++++++++++++++++++++--
 dlls/msvcrt/msvcrt.h       |    1 +
 dlls/msvcrt/msvcrt.spec    |    4 +--
 dlls/msvcrt/string.c       |   22 +++++++++++++++
 dlls/msvcrt/tests/string.c |   17 ++++++++++++
 5 files changed, 102 insertions(+), 5 deletions(-)


diff --git a/dlls/msvcrt/errno.c b/dlls/msvcrt/errno.c
index 413ab39..03cf0a8 100644
--- a/dlls/msvcrt/errno.c
+++ b/dlls/msvcrt/errno.c
@@ -23,6 +23,7 @@
 
 #include "msvcrt.h"
 #include "wine/debug.h"
+#include <errno.h>
 
 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
 
@@ -121,7 +122,7 @@ unsigned int MSVCRT__sys_nerr = sizeof(MSVCRT__sys_errlist)/sizeof(MSVCRT__sys_e
 /* INTERNAL: Set the crt and dos errno's from the OS error given. */
 void msvcrt_set_errno(int err)
 {
-  int *errno = MSVCRT__errno();
+  int *msvcrt_errno = MSVCRT__errno();
   MSVCRT_ulong *doserrno = MSVCRT___doserrno();
 
   *doserrno = err;
@@ -129,7 +130,7 @@ void msvcrt_set_errno(int err)
   switch(err)
   {
 #define ERR_CASE(oserr) case oserr:
-#define ERR_MAPS(oserr, crterr) case oserr: *errno = crterr; break
+#define ERR_MAPS(oserr, crterr) case oserr: *msvcrt_errno = crterr; break
     ERR_CASE(ERROR_ACCESS_DENIED)
     ERR_CASE(ERROR_NETWORK_ACCESS_DENIED)
     ERR_CASE(ERROR_CANNOT_MAKE)
@@ -175,7 +176,63 @@ void msvcrt_set_errno(int err)
   default:
     /*  Remaining cases map to EINVAL */
     /* FIXME: may be missing some errors above */
-    *errno = MSVCRT_EINVAL;
+    *msvcrt_errno = MSVCRT_EINVAL;
+  }
+}
+
+void msvcrt_set_unix_errno(void)
+{
+  int *msvcrt_errno = MSVCRT__errno();
+  MSVCRT_ulong *doserrno = MSVCRT___doserrno();
+
+  *doserrno = 0; /* FIXME */
+
+  /* unfortunetaly the errno's don't fully match. do it the hard way */
+  switch (errno)
+  {
+#define X(e)    case e: *msvcrt_errno = MSVCRT_ ## e; break
+      X(EPERM);
+      X(ENOENT);
+      X(ESRCH);
+      X(EINTR);
+      X(EIO);
+      X(ENXIO);
+      X(E2BIG);
+      X(ENOEXEC);
+      X(EBADF);
+      X(ECHILD);
+      X(EAGAIN);
+      X(ENOMEM);
+      X(EACCES);
+      X(EFAULT);
+      X(EBUSY);
+      X(EEXIST);
+      X(EXDEV);
+      X(ENODEV);
+      X(ENOTDIR);
+      X(EISDIR);
+      X(EINVAL);
+      X(ENFILE);
+      X(EMFILE);
+      X(ENOTTY);
+      X(EFBIG);
+      X(ENOSPC);
+      X(ESPIPE);
+      X(EROFS);
+      X(EMLINK);
+      X(EPIPE);
+      X(EDOM);
+      X(ERANGE);
+      X(EDEADLOCK);
+      X(ENAMETOOLONG);
+      X(ENOLCK);
+      X(ENOSYS);
+      X(ENOTEMPTY);
+      X(EILSEQ);
+#undef X
+  default:
+    /*  Remaining cases map to EINVAL */
+    *msvcrt_errno = MSVCRT_EINVAL;
   }
 }
 
diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h
index 7edcd6d..b9e759a 100644
--- a/dlls/msvcrt/msvcrt.h
+++ b/dlls/msvcrt/msvcrt.h
@@ -123,6 +123,7 @@ extern WORD MSVCRT_current_ctype[257];
 extern WORD* MSVCRT__pctype;
 
 void   msvcrt_set_errno(int);
+void   msvcrt_set_unix_errno(void);
 
 void __cdecl _purecall(void);
 void __cdecl _amsg_exit(int errnum);
diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec
index fd03647..5c475a0 100644
--- a/dlls/msvcrt/msvcrt.spec
+++ b/dlls/msvcrt/msvcrt.spec
@@ -767,8 +767,8 @@
 @ cdecl strstr(str str) ntdll.strstr
 @ cdecl strtod(str ptr) MSVCRT_strtod
 @ cdecl strtok(str str) MSVCRT_strtok
-@ cdecl strtol(str ptr long) ntdll.strtol
-@ cdecl strtoul(str ptr long) ntdll.strtoul
+@ cdecl strtol(str ptr long) MSVCRT_strtol
+@ cdecl strtoul(str ptr long) MSVCRT_strtoul
 @ cdecl strxfrm(ptr str long) MSVCRT_strxfrm
 @ varargs swprintf(ptr wstr) MSVCRT_swprintf
 @ varargs swscanf(wstr wstr) MSVCRT_swscanf
diff --git a/dlls/msvcrt/string.c b/dlls/msvcrt/string.c
index 74beefb..011bee5 100644
--- a/dlls/msvcrt/string.c
+++ b/dlls/msvcrt/string.c
@@ -250,3 +250,25 @@ int CDECL __STRINGTOLD( MSVCRT__LDOUBLE *value, char **endptr, const char *str,
 #endif
     return 0;
 }
+
+/******************************************************************
+ *		strtol (MSVCRT.@)
+ */
+long int MSVCRT_strtol(const char* nptr, char** end, int base)
+{
+    /* wrapper to forward libc error code to msvcrt's error codes */
+    long ret = strtol(nptr, end, base);
+    msvcrt_set_unix_errno();
+    return ret;
+}
+
+/******************************************************************
+ *		strtoul (MSVCRT.@)
+ */
+unsigned long int MSVCRT_strtoul(const char* nptr, char** end, int base)
+{
+    /* wrapper to forward libc error code to msvcrt's error codes */
+    unsigned long ret = strtoul(nptr, end, base);
+    msvcrt_set_unix_errno();
+    return ret;
+}
diff --git a/dlls/msvcrt/tests/string.c b/dlls/msvcrt/tests/string.c
index 96bcb7f..186f133 100644
--- a/dlls/msvcrt/tests/string.c
+++ b/dlls/msvcrt/tests/string.c
@@ -663,6 +663,22 @@ static void test_strtok(void)
     }
 }
 
+static void test_strtol(void)
+{
+    char* e;
+    long l;
+    unsigned long ul;
+
+    errno = 0;
+    l = strtol("9223372036854775807L", &e, 0);
+    ok(l==2147483647, "wrong value %ld\n", l);
+    ok(errno == ERANGE, "wrong errno %d\n", errno);
+    errno = 0;
+    ul = strtoul("9223372036854775807L", &e, 0);
+    ok(ul==4294967295ul, "wrong value %lu\n", ul);
+    ok(errno == ERANGE, "wrong errno %d\n", errno);
+}
+
 START_TEST(string)
 {
     char mem[100];
@@ -706,4 +722,5 @@ START_TEST(string)
     test_mbcjisjms();
     test_strtok();
     test_wcscpy_s();
+    test_strtol();
 }






More information about the wine-patches mailing list