From 5fcb637cb20323d492dcaf3d349cff577b865258 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Wed, 19 Sep 2012 22:33:13 +0000 Subject: [PATCH] [CRT] Implement mbstowcs_s. passes all crt apitests. svn path=/trunk/; revision=57345 --- reactos/dll/win32/msvcrt/msvcrt.spec | 2 +- reactos/lib/sdk/crt/crt.cmake | 1 + reactos/lib/sdk/crt/string/mbstowcs_s.c | 117 ++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 reactos/lib/sdk/crt/string/mbstowcs_s.c diff --git a/reactos/dll/win32/msvcrt/msvcrt.spec b/reactos/dll/win32/msvcrt/msvcrt.spec index 9b6a73fdf12..8ac2e5643e9 100644 --- a/reactos/dll/win32/msvcrt/msvcrt.spec +++ b/reactos/dll/win32/msvcrt/msvcrt.spec @@ -1272,7 +1272,7 @@ # stub mbsrtowcs # stub mbsrtowcs_s @ cdecl mbstowcs(ptr str long) -# stub mbstowcs_s +@ cdecl mbstowcs_s(ptr ptr long str long) @ cdecl mbtowc(wstr str long) @ cdecl memchr(ptr long long) @ cdecl memcmp(ptr ptr long) diff --git a/reactos/lib/sdk/crt/crt.cmake b/reactos/lib/sdk/crt/crt.cmake index 226f45fdaea..a46055827bf 100644 --- a/reactos/lib/sdk/crt/crt.cmake +++ b/reactos/lib/sdk/crt/crt.cmake @@ -256,6 +256,7 @@ list(APPEND CRT_SOURCE string/is_wctype.c string/itoa.c string/itow.c + string/mbstowcs_s.c string/scanf.c string/splitp.c string/strcoll.c diff --git a/reactos/lib/sdk/crt/string/mbstowcs_s.c b/reactos/lib/sdk/crt/string/mbstowcs_s.c new file mode 100644 index 00000000000..6442cd1aae6 --- /dev/null +++ b/reactos/lib/sdk/crt/string/mbstowcs_s.c @@ -0,0 +1,117 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS CRT + * PURPOSE: Implementation of mbstowcs_s + * FILE: lib/sdk/crt/stdlib/mbstowcs_s.c + * PROGRAMMER: Timo Kreuzer + */ + +#include +#include + +#define _mbsnlen strnlen + +_CRTIMP +_Check_return_opt_ +errno_t +__cdecl +mbstowcs_s( + _Out_opt_ size_t *pReturnValue, + _Out_writes_to_opt_(sizeInWords, *pReturnValue) wchar_t *pwcstr, + _In_ size_t sizeInWords, + _In_reads_or_z_(count) const char *pmbstr, + _In_ size_t count) +{ + size_t cchMax, cwcWritten; + errno_t retval = 0; + + /* Make sure, either we have a target buffer > 0 bytes, or no buffer */ + if (!MSVCRT_CHECK_PMT( ((sizeInWords != 0) && (pwcstr != 0)) || + ((sizeInWords == 0) && (pwcstr == 0)) )) + { + _set_errno(EINVAL); + return EINVAL; + } + + /* Check if we have a return value pointer */ + if (pReturnValue) + { + /* Default to 0 bytes written */ + *pReturnValue = 0; + } + + if (!MSVCRT_CHECK_PMT((count == 0) || (pmbstr != 0))) + { + _set_errno(EINVAL); + return EINVAL; + } + + /* Check if there is anything to do */ + if ((pwcstr == 0) && (pmbstr == 0)) + { + _set_errno(EINVAL); + return EINVAL; + } + + /* Check if we have a multibyte string */ + if (pmbstr) + { + /* Check if we also have a wchar buffer */ + if (pwcstr) + { + /* Calculate the maximum the we can write */ + cchMax = (count < sizeInWords) ? count + 1 : sizeInWords; + + /* Now do the conversion */ + cwcWritten = mbstowcs(pwcstr, pmbstr, cchMax); + + /* Check if the buffer was not zero terminated */ + if (cwcWritten == cchMax) + { + /* Check if we reached the max size of the dest buffer */ + if (cwcWritten == sizeInWords) + { + /* Does the caller allow this? */ + if (count != _TRUNCATE) + { + /* Not allowed, truncate to 0 length */ + pwcstr[0] = L'\0'; + + /* Return error */ + _set_errno(ERANGE); + return ERANGE; + } + + /* Inform the caller about truncation */ + retval = STRUNCATE; + } + + /* zero teminate the buffer */ + pwcstr[cwcWritten - 1] = L'\0'; + } + else + { + /* The buffer is zero terminated, count the terminating char */ + cwcWritten++; + } + } + else + { + /* Get the length of the string, plus 0 terminator */ + cwcWritten = _mbsnlen(pmbstr, count) + 1; + } + } + else + { + cwcWritten = count + 1; + } + + /* Check if we have a return value pointer */ + if (pReturnValue) + { + /* Default to 0 bytes written */ + *pReturnValue = cwcWritten; + } + + return retval; +}