Module: wine Branch: master Commit: 8fc18b6b4801efc0098f20a6ed4cacf6172e986f URL: http://source.winehq.org/git/wine.git/?a=commit;h=8fc18b6b4801efc0098f20a6ed...
Author: Piotr Caban piotr@codeweavers.com Date: Mon Apr 12 15:35:31 2010 +0200
msvcrt: Added memmove_s and memcpy_s implementation.
---
dlls/msvcr80/msvcr80.spec | 4 +- dlls/msvcr90/msvcr90.spec | 4 +- dlls/msvcrt/heap.c | 29 +++++++++++++++++++++++ dlls/msvcrt/msvcrt.spec | 4 +- dlls/msvcrt/tests/misc.c | 55 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 90 insertions(+), 6 deletions(-)
diff --git a/dlls/msvcr80/msvcr80.spec b/dlls/msvcr80/msvcr80.spec index d7d0395..7d170a9 100644 --- a/dlls/msvcr80/msvcr80.spec +++ b/dlls/msvcr80/msvcr80.spec @@ -1335,9 +1335,9 @@ @ cdecl memchr(ptr long long) msvcrt.memchr @ cdecl memcmp(ptr ptr long) msvcrt.memcmp @ cdecl memcpy(ptr ptr long) msvcrt.memcpy -@ stub memcpy_s +@ cdecl memcpy_s(ptr long ptr long) msvcrt.memcpy_s @ cdecl memmove(ptr ptr long) msvcrt.memmove -@ stub memmove_s +@ cdecl memmove_s(ptr long ptr long) msvcrt.memmove_s @ cdecl memset(ptr long long) msvcrt.memset @ cdecl modf(double ptr) msvcrt.modf @ cdecl perror(str) msvcrt.perror diff --git a/dlls/msvcr90/msvcr90.spec b/dlls/msvcr90/msvcr90.spec index 9bfa23d..3eae9a0 100644 --- a/dlls/msvcr90/msvcr90.spec +++ b/dlls/msvcr90/msvcr90.spec @@ -1319,9 +1319,9 @@ @ cdecl memchr(ptr long long) msvcrt.memchr @ cdecl memcmp(ptr ptr long) msvcrt.memcmp @ cdecl memcpy(ptr ptr long) msvcrt.memcpy -@ stub memcpy_s +@ cdecl memcpy_s(ptr long ptr long) msvcrt.memcpy_s @ cdecl memmove(ptr ptr long) msvcrt.memmove -@ stub memmove_s +@ cdecl memmove_s(ptr long ptr long) msvcrt.memmove_s @ cdecl memset(ptr long long) msvcrt.memset @ cdecl modf(double ptr) msvcrt.modf @ cdecl perror(str) msvcrt.perror diff --git a/dlls/msvcrt/heap.c b/dlls/msvcrt/heap.c index e40a0c9..7adaf90 100644 --- a/dlls/msvcrt/heap.c +++ b/dlls/msvcrt/heap.c @@ -511,3 +511,32 @@ void * CDECL _aligned_realloc(void *memblock, MSVCRT_size_t size, MSVCRT_size_t TRACE("(%p, %lu, %lu)\n", memblock, size, alignment); return _aligned_offset_realloc(memblock, size, alignment, 0); } + +/********************************************************************* + * memmove_s (MSVCRT.@) + */ +int CDECL memmove_s(void *dest, MSVCRT_size_t numberOfElements, const void *src, MSVCRT_size_t count) +{ + TRACE("(%p %lu %p %lu)\n", dest, numberOfElements, src, count); + + if(!count) + return 0; + + if(!dest || !src) { + if(dest) + memset(dest, 0, numberOfElements); + + *MSVCRT__errno() = MSVCRT_EINVAL; + return MSVCRT_EINVAL; + } + + if(count > numberOfElements) { + memset(dest, 0, numberOfElements); + + *MSVCRT__errno() = MSVCRT_ERANGE; + return MSVCRT_ERANGE; + } + + memmove(dest, src, count); + return 0; +} diff --git a/dlls/msvcrt/msvcrt.spec b/dlls/msvcrt/msvcrt.spec index eac8f46..08b330f 100644 --- a/dlls/msvcrt/msvcrt.spec +++ b/dlls/msvcrt/msvcrt.spec @@ -1267,9 +1267,9 @@ @ cdecl memchr(ptr long long) ntdll.memchr @ cdecl memcmp(ptr ptr long) ntdll.memcmp @ cdecl memcpy(ptr ptr long) ntdll.memcpy -# stub memcpy_s +@ cdecl memcpy_s(ptr long ptr long) memmove_s @ cdecl memmove(ptr ptr long) ntdll.memmove -# stub memmove_s +@ cdecl memmove_s(ptr long ptr long) @ cdecl memset(ptr long long) ntdll.memset @ cdecl mktime(ptr) MSVCRT_mktime @ cdecl modf(double ptr) MSVCRT_modf diff --git a/dlls/msvcrt/tests/misc.c b/dlls/msvcrt/tests/misc.c index 1f069fa..d8b1b88 100644 --- a/dlls/msvcrt/tests/misc.c +++ b/dlls/msvcrt/tests/misc.c @@ -20,14 +20,17 @@
#include "wine/test.h" #include <errno.h> +#include "msvcrt.h"
static int (__cdecl *prand_s)(unsigned int *); +static int (__cdecl *memcpy_s)(void *, MSVCRT_size_t, void*, MSVCRT_size_t);
static void init(void) { HMODULE hmod = GetModuleHandleA("msvcrt.dll");
prand_s = (void *)GetProcAddress(hmod, "rand_s"); + memcpy_s = (void*)GetProcAddress(hmod, "memcpy_s"); }
static void test_rand_s(void) @@ -50,9 +53,61 @@ static void test_rand_s(void) ok(ret == 0, "Expected rand_s to return 0, got %d\n", ret); }
+static void test_memcpy_s(void) +{ + static char data[] = "data\0to\0be\0copied"; + static char dest[32]; + int ret; + + if(!memcpy_s) + { + win_skip("memcpy_s in not available\n"); + return; + } + + errno = 0xdeadbeef; + ret = memcpy_s(NULL, 0, NULL, 0); + ok(ret == 0, "ret = %x\n", ret); + ok(errno == 0xdeadbeef, "errno = %x\n", errno); + + errno = 0xdeadbeef; + dest[0] = 'x'; + ret = memcpy_s(dest, 10, NULL, 0); + ok(ret == 0, "ret = %x\n", ret); + ok(errno == 0xdeadbeef, "errno = %x\n", errno); + ok(dest[0] == 'x', "dest[0] != 'x'\n"); + + errno = 0xdeadbeef; + ret = memcpy_s(NULL, 10, data, 10); + ok(ret == EINVAL, "ret = %x\n", ret); + ok(errno == EINVAL, "errno = %x\n", errno); + + errno = 0xdeadbeef; + dest[7] = 'x'; + ret = memcpy_s(dest, 10, data, 5); + ok(ret == 0, "ret = %x\n", ret); + ok(errno == 0xdeadbeef, "errno = %x\n", errno); + ok(memcmp(dest, data, 10), "All data copied\n"); + ok(!memcmp(dest, data, 5), "First five bytes are different\n"); + + errno = 0xdeadbeef; + ret = memcpy_s(data, 10, data, 10); + ok(ret == 0, "ret = %x\n", ret); + ok(errno == 0xdeadbeef, "errno = %x\n", errno); + ok(!memcmp(dest, data, 5), "data was destroyed during overwritting\n"); + + errno = 0xdeadbeef; + dest[0] = 'x'; + ret = memcpy_s(dest, 5, data, 10); + ok(ret == ERANGE, "ret = %x\n", ret); + ok(errno == ERANGE, "errno = %x\n", errno); + ok(dest[0] == '\0', "dest[0] != '\0'\n"); +} + START_TEST(misc) { init();
test_rand_s(); + test_memcpy_s(); }