From 101abcd8b119853ff70449be27e2322b16bbaf47 Mon Sep 17 00:00:00 2001 From: Piotr Caban Date: Wed, 12 Dec 2012 11:14:48 +0100 Subject: [PATCH] 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 577894015e7..f529b10e8f1 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" @@ -403,6 +404,59 @@ unsigned __int64 CDECL _byteswap_uint64(unsigned __int64 i) ((i>>8)&0xFF000000) + ((i>>24)&0xFF0000) + ((i>>40)&0xFF00) + (i>>56); } +/********************************************************************* + * 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_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.@) */ diff --git a/dlls/msvcr100/msvcr100.spec b/dlls/msvcr100/msvcr100.spec index 162ad65b04c..70fca053817 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 366e8eeb593..143979d3ee1 100644 --- a/dlls/msvcr100/tests/msvcr100.c +++ b/dlls/msvcr100/tests/msvcr100.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -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 e9274f5366b..2eecb7a45ba 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 3b18f436e22..8644692fcac 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 938da762801..d0f058b1711 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 */