Sync with trunk r58033.
[reactos.git] / lib / sdk / crt / string / mbstowcs_s.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS CRT
4 * PURPOSE: Implementation of mbstowcs_s
5 * FILE: lib/sdk/crt/stdlib/mbstowcs_s.c
6 * PROGRAMMER: Timo Kreuzer
7 */
8
9 #include <precomp.h>
10 #include <mbstring.h>
11
12 _Success_(return!=EINVAL)
13 _Check_return_opt_
14 _CRTIMP
15 errno_t
16 __cdecl
17 mbstowcs_s(
18 _Out_opt_ size_t *pcchConverted,
19 _Out_writes_to_opt_(sizeInWords, *pcchConverted) wchar_t *pwcstr,
20 _In_ size_t sizeInWords,
21 _In_reads_or_z_(count) const char *pmbstr,
22 _In_ size_t count)
23 {
24 size_t cchMax, cwcWritten;
25 errno_t retval = 0;
26
27 /* Make sure, either we have a target buffer > 0 bytes, or no buffer */
28 if (!MSVCRT_CHECK_PMT( ((sizeInWords != 0) && (pwcstr != 0)) ||
29 ((sizeInWords == 0) && (pwcstr == 0)) ))
30 {
31 _set_errno(EINVAL);
32 return EINVAL;
33 }
34
35 /* Check if we have a return value pointer */
36 if (pcchConverted)
37 {
38 /* Default to 0 bytes written */
39 *pcchConverted = 0;
40 }
41
42 if (!MSVCRT_CHECK_PMT((count == 0) || (pmbstr != 0)))
43 {
44 _set_errno(EINVAL);
45 return EINVAL;
46 }
47
48 /* Check if there is anything to do */
49 if ((pwcstr == 0) && (pmbstr == 0))
50 {
51 _set_errno(EINVAL);
52 return EINVAL;
53 }
54
55 /* Check if we have a multibyte string */
56 if (pmbstr)
57 {
58 /* Check if we also have a wchar buffer */
59 if (pwcstr)
60 {
61 /* Calculate the maximum the we can write */
62 cchMax = (count < sizeInWords) ? count + 1 : sizeInWords;
63
64 /* Now do the conversion */
65 cwcWritten = mbstowcs(pwcstr, pmbstr, cchMax);
66
67 /* Check if the buffer was not zero terminated */
68 if (cwcWritten == cchMax)
69 {
70 /* Check if we reached the max size of the dest buffer */
71 if (cwcWritten == sizeInWords)
72 {
73 /* Does the caller allow this? */
74 if (count != _TRUNCATE)
75 {
76 /* Not allowed, truncate to 0 length */
77 pwcstr[0] = L'\0';
78
79 /* Return error */
80 _set_errno(ERANGE);
81 return ERANGE;
82 }
83
84 /* Inform the caller about truncation */
85 retval = STRUNCATE;
86 }
87
88 /* zero teminate the buffer */
89 pwcstr[cwcWritten - 1] = L'\0';
90 }
91 else
92 {
93 /* The buffer is zero terminated, count the terminating char */
94 cwcWritten++;
95 }
96 }
97 else
98 {
99 /* Get the length of the string, plus 0 terminator */
100 cwcWritten = _mbsnlen((const unsigned char *)pmbstr, count) + 1;
101 }
102 }
103 else
104 {
105 cwcWritten = count + 1;
106 }
107
108 /* Check if we have a return value pointer */
109 if (pcchConverted)
110 {
111 /* Default to 0 bytes written */
112 *pcchConverted = cwcWritten;
113 }
114
115 return retval;
116 }