Piotr Caban : msvcr100: Added fread_s implementation.

Alexandre Julliard julliard at winehq.org
Wed Dec 12 15:14:54 CST 2012


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

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Wed Dec 12 11:14:48 2012 +0100

msvcr100: Added fread_s implementation.

---

 dlls/msvcr100/msvcr100.c       |   54 +++++++++++++++++++++++++++
 dlls/msvcr100/msvcr100.spec    |    2 +-
 dlls/msvcr100/tests/msvcr100.c |   80 ++++++++++++++++++++++++++++++++++++++++
 dlls/msvcr80/msvcr80.spec      |    2 +-
 dlls/msvcr90/msvcr90.spec      |    2 +-
 include/msvcrt/limits.h        |    8 ++++
 6 files changed, 145 insertions(+), 3 deletions(-)

diff --git a/dlls/msvcr100/msvcr100.c b/dlls/msvcr100/msvcr100.c
index 5778940..f529b10 100644
--- a/dlls/msvcr100/msvcr100.c
+++ b/dlls/msvcr100/msvcr100.c
@@ -25,6 +25,7 @@
 #include "stdlib.h"
 #include "errno.h"
 #include "malloc.h"
+#include "limits.h"
 #include "sys/stat.h"
 #include "windef.h"
 #include "winbase.h"
@@ -404,6 +405,59 @@ unsigned __int64 CDECL _byteswap_uint64(unsigned __int64 i)
 }
 
 /*********************************************************************
+ * fread_s (MSVCR100.@)
+ */
+size_t CDECL fread_s(void *buf, size_t buf_size, size_t elem_size, size_t count, FILE *stream)
+{
+    size_t bytes_left, buf_pos;
+
+    TRACE("(%p %lu %lu %lu %p\n", buf, (unsigned long)buf_size,
+            (unsigned long)elem_size, (unsigned long)count, stream);
+
+
+    if(!CHECK_PMT(stream != NULL)) {
+        if(buf && buf_size)
+            memset(buf, 0, buf_size);
+        return 0;
+    }
+    if(!elem_size || !count) return 0;
+    if(!CHECK_PMT(buf != NULL)) return 0;
+    if(!CHECK_PMT(SIZE_MAX/count >= elem_size)) return 0;
+
+    bytes_left = elem_size*count;
+    buf_pos = 0;
+    while(bytes_left) {
+        if(stream->_cnt > 0) {
+            size_t size = bytes_left<stream->_cnt ? bytes_left : stream->_cnt;
+
+            if(!CHECK_PMT_ERR(size <= buf_size-buf_pos, ERANGE)) {
+                memset(buf, 0, buf_size);
+                return 0;
+            }
+
+            fread((char*)buf+buf_pos, 1, size, stream);
+            buf_pos += size;
+            bytes_left -= size;
+        }else {
+            int c = _filbuf(stream);
+
+            if(c == EOF)
+                break;
+
+            if(!CHECK_PMT_ERR(buf_size-buf_pos > 0, ERANGE)) {
+                memset(buf, 0, buf_size);
+                return 0;
+            }
+
+            ((char*)buf)[buf_pos++] = c;
+            bytes_left--;
+        }
+    }
+
+    return buf_pos/elem_size;
+}
+
+/*********************************************************************
  *  DllMain (MSVCR100.@)
  */
 BOOL WINAPI DllMain(HINSTANCE hdll, DWORD reason, LPVOID reserved)
diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec
index 162ad65..70fca053 100644
--- a/dlls/msvcr100/msvcr100.spec
+++ b/dlls/msvcr100/msvcr100.spec
@@ -1669,7 +1669,7 @@
 @ cdecl fputwc(long ptr) msvcrt.fputwc
 @ cdecl fputws(wstr ptr) msvcrt.fputws
 @ cdecl fread(ptr long long ptr) msvcrt.fread
-@ stub fread_s
+@ cdecl fread_s(ptr long long long ptr)
 @ cdecl free(ptr) msvcrt.free
 @ cdecl freopen(str str ptr) msvcrt.freopen
 @ cdecl freopen_s(ptr str str ptr) msvcrt.freopen_s
diff --git a/dlls/msvcr100/tests/msvcr100.c b/dlls/msvcr100/tests/msvcr100.c
index 366e8ee..143979d 100644
--- a/dlls/msvcr100/tests/msvcr100.c
+++ b/dlls/msvcr100/tests/msvcr100.c
@@ -20,6 +20,7 @@
 #include <stdarg.h>
 #include <stdlib.h>
 #include <wchar.h>
+#include <stdio.h>
 
 #include <windef.h>
 #include <winbase.h>
@@ -68,6 +69,9 @@ static void __cdecl test_invalid_parameter_handler(const wchar_t *expression,
 static int* (__cdecl *p_errno)(void);
 static int (__cdecl *p_wmemcpy_s)(wchar_t *dest, size_t numberOfElements, const wchar_t *src, size_t count);
 static int (__cdecl *p_wmemmove_s)(wchar_t *dest, size_t numberOfElements, const wchar_t *src, size_t count);
+static FILE* (__cdecl *p_fopen)(const char*,const char*);
+static int (__cdecl *p_fclose)(FILE*);
+static size_t (__cdecl *p_fread_s)(void*,size_t,size_t,size_t,FILE*);
 
 /* make sure we use the correct errno */
 #undef errno
@@ -91,6 +95,9 @@ static BOOL init(void)
     SET(p_set_invalid_parameter_handler, "_set_invalid_parameter_handler");
     SET(p_wmemcpy_s, "wmemcpy_s");
     SET(p_wmemmove_s, "wmemmove_s");
+    SET(p_fopen, "fopen");
+    SET(p_fclose, "fclose");
+    SET(p_fread_s, "fread_s");
 
     return TRUE;
 }
@@ -247,6 +254,78 @@ static void test_wmemmove_s(void)
             "Cannot reset invalid parameter handler\n");
 }
 
+static void test_fread_s(void)
+{
+    static const char test_file[] = "fread_s.tst";
+    int ret;
+    char buf[10];
+
+    FILE *f = fopen(test_file, "w");
+    if(!f) {
+        skip("Error creating test file\n");
+        return;
+    }
+    fwrite("test", 1, 4, f);
+    fclose(f);
+
+    ok(p_set_invalid_parameter_handler(test_invalid_parameter_handler) == NULL,
+            "Invalid parameter handler was already set\n");
+
+    SET_EXPECT(invalid_parameter_handler);
+    errno = 0xdeadbeef;
+    ret = p_fread_s(buf, sizeof(buf), 1, 1, NULL);
+    ok(ret == 0, "fread_s returned %d, expected 0\n", ret);
+    ok(errno == EINVAL, "errno = %d, expected EINVAL\n", errno);
+    CHECK_CALLED(invalid_parameter_handler);
+
+    f = p_fopen(test_file, "r");
+    errno = 0xdeadbeef;
+    ret = p_fread_s(NULL, sizeof(buf), 0, 1, f);
+    ok(ret == 0, "fread_s returned %d, expected 0\n", ret);
+    ok(errno == 0xdeadbeef, "errno = %d, expected 0xdeadbeef\n", errno);
+    ret = p_fread_s(NULL, sizeof(buf), 1, 0, f);
+    ok(ret == 0, "fread_s returned %d, expected 0\n", ret);
+    ok(errno == 0xdeadbeef, "errno = %d, expected 0xdeadbeef\n", errno);
+
+    SET_EXPECT(invalid_parameter_handler);
+    errno = 0xdeadbeef;
+    ret = p_fread_s(NULL, sizeof(buf), 1, 1, f);
+    ok(ret == 0, "fread_s returned %d, expected 0\n", ret);
+    ok(errno == EINVAL, "errno = %d, expected EINVAL\n", errno);
+    CHECK_CALLED(invalid_parameter_handler);
+
+    SET_EXPECT(invalid_parameter_handler);
+    errno = 0xdeadbeef;
+    buf[1] = 'a';
+    ret = p_fread_s(buf, 3, 1, 10, f);
+    ok(ret == 0, "fread_s returned %d, expected 0\n", ret);
+    ok(buf[0] == 0, "buf[0] = '%c', expected 0\n", buf[0]);
+    ok(buf[1] == 0, "buf[1] = '%c', expected 0\n", buf[1]);
+    ok(errno == ERANGE, "errno = %d, expected ERANGE\n", errno);
+    CHECK_CALLED(invalid_parameter_handler);
+
+    SET_EXPECT(invalid_parameter_handler);
+    errno = 0xdeadbeef;
+    ret = p_fread_s(buf, 2, 1, 10, f);
+    ok(ret == 0, "fread_s returned %d, expected 0\n", ret);
+    ok(buf[0] == 0, "buf[0] = '%c', expected 0\n", buf[0]);
+    ok(errno == ERANGE, "errno = %d, expected ERANGE\n", errno);
+    CHECK_CALLED(invalid_parameter_handler);
+
+    memset(buf, 'a', sizeof(buf));
+    ret = p_fread_s(buf, sizeof(buf), 3, 10, f);
+    ok(ret==1, "fread_s returned %d, expected 1\n", ret);
+    ok(buf[0] == 'e', "buf[0] = '%c', expected 'e'\n", buf[0]);
+    ok(buf[1] == 's', "buf[1] = '%c', expected 's'\n", buf[1]);
+    ok(buf[2] == 't', "buf[2] = '%c', expected 't'\n", buf[2]);
+    ok(buf[3] == 'a', "buf[3] = '%c', expected 'a'\n", buf[3]);
+    p_fclose(f);
+
+    ok(p_set_invalid_parameter_handler(NULL) == test_invalid_parameter_handler,
+            "Cannot reset invalid parameter handler\n");
+    unlink(test_file);
+}
+
 START_TEST(msvcr100)
 {
     if (!init())
@@ -254,4 +333,5 @@ START_TEST(msvcr100)
 
     test_wmemcpy_s();
     test_wmemmove_s();
+    test_fread_s();
 }
diff --git a/dlls/msvcr80/msvcr80.spec b/dlls/msvcr80/msvcr80.spec
index e9274f5..2eecb7a 100644
--- a/dlls/msvcr80/msvcr80.spec
+++ b/dlls/msvcr80/msvcr80.spec
@@ -1323,7 +1323,7 @@
 @ cdecl fputwc(long ptr) msvcrt.fputwc
 @ cdecl fputws(wstr ptr) msvcrt.fputws
 @ cdecl fread(ptr long long ptr) msvcrt.fread
-@ stub fread_s
+@ cdecl fread_s(ptr long long long ptr) msvcr100.fread_s
 @ cdecl free(ptr) msvcrt.free
 @ cdecl freopen(str str ptr) msvcrt.freopen
 @ cdecl freopen_s(ptr str str ptr) msvcrt.freopen_s
diff --git a/dlls/msvcr90/msvcr90.spec b/dlls/msvcr90/msvcr90.spec
index 3b18f43..8644692 100644
--- a/dlls/msvcr90/msvcr90.spec
+++ b/dlls/msvcr90/msvcr90.spec
@@ -1324,7 +1324,7 @@
 @ cdecl fputwc(long ptr) msvcrt.fputwc
 @ cdecl fputws(wstr ptr) msvcrt.fputws
 @ cdecl fread(ptr long long ptr) msvcrt.fread
-@ stub fread_s
+@ cdecl fread_s(ptr long long long ptr) msvcr100.fread_s
 @ cdecl free(ptr) msvcrt.free
 @ cdecl freopen(str str ptr) msvcrt.freopen
 @ cdecl freopen_s(ptr str str ptr) msvcrt.freopen_s
diff --git a/include/msvcrt/limits.h b/include/msvcrt/limits.h
index 938da76..d0f058b 100644
--- a/include/msvcrt/limits.h
+++ b/include/msvcrt/limits.h
@@ -38,4 +38,12 @@
 #define I64_MAX  _I64_MAX
 #define UI64_MAX _UI64_MAX
 
+#ifndef SIZE_MAX
+# ifdef _WIN64
+#  define SIZE_MAX UI64_MAX
+# else
+#  define SIZE_MAX UINT_MAX
+# endif
+#endif
+
 #endif /* __WINE_LIMITS_H */




More information about the wine-cvs mailing list