1c2c66affSColin Finck /*
2c2c66affSColin Finck * PROJECT: ReactOS CRT library
3c2c66affSColin Finck * LICENSE: LGPL - See COPYING in the top level directory
4c2c66affSColin Finck * FILE: lib/sdk/crt/string/wcs.c
5c2c66affSColin Finck * PURPOSE: wcs* CRT functions
6c2c66affSColin Finck * PROGRAMMERS: Wine team
7c2c66affSColin Finck * Ported to ReactOS by Aleksey Bragin (aleksey@reactos.org)
8c2c66affSColin Finck */
9c2c66affSColin Finck
10c2c66affSColin Finck /*
11c2c66affSColin Finck * msvcrt.dll wide-char functions
12c2c66affSColin Finck *
13c2c66affSColin Finck * Copyright 1999 Alexandre Julliard
14c2c66affSColin Finck * Copyright 2000 Jon Griffiths
15c2c66affSColin Finck *
16c2c66affSColin Finck * This library is free software; you can redistribute it and/or
17c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
18c2c66affSColin Finck * License as published by the Free Software Foundation; either
19c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
20c2c66affSColin Finck *
21c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
22c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
23c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24c2c66affSColin Finck * Lesser General Public License for more details.
25c2c66affSColin Finck *
26c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
27c2c66affSColin Finck * License along with this library; if not, write to the Free Software
28c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29c2c66affSColin Finck */
30c2c66affSColin Finck #include <precomp.h>
31c2c66affSColin Finck #include <assert.h>
32c2c66affSColin Finck
33c2c66affSColin Finck #ifndef _LIBCNT_
34c2c66affSColin Finck #include <internal/wine/msvcrt.h>
35c2c66affSColin Finck #endif
36c2c66affSColin Finck
37c2c66affSColin Finck #include "wine/unicode.h"
38c2c66affSColin Finck #undef sprintf
39c2c66affSColin Finck #undef wsprintf
40c2c66affSColin Finck #undef snprintf
41c2c66affSColin Finck #undef vsnprintf
42c2c66affSColin Finck #undef vprintf
43c2c66affSColin Finck #undef vwprintf
44c2c66affSColin Finck
45c2c66affSColin Finck #ifdef _MSC_VER
46c2c66affSColin Finck #pragma function(_wcsset)
47c2c66affSColin Finck #endif
48c2c66affSColin Finck
49c2c66affSColin Finck #ifndef _LIBCNT_
50c2c66affSColin Finck /*********************************************************************
51c2c66affSColin Finck * _wcsdup (MSVCRT.@)
52c2c66affSColin Finck */
_wcsdup(const wchar_t * str)53c2c66affSColin Finck wchar_t* CDECL _wcsdup( const wchar_t* str )
54c2c66affSColin Finck {
55c2c66affSColin Finck wchar_t* ret = NULL;
56c2c66affSColin Finck if (str)
57c2c66affSColin Finck {
58c2c66affSColin Finck size_t size = (strlenW(str) + 1) * sizeof(wchar_t);
59c2c66affSColin Finck ret = malloc( size );
60c2c66affSColin Finck if (ret) memcpy( ret, str, size );
61c2c66affSColin Finck }
62c2c66affSColin Finck return ret;
63c2c66affSColin Finck }
64c2c66affSColin Finck /*********************************************************************
65c2c66affSColin Finck * _wcsicoll (MSVCRT.@)
66c2c66affSColin Finck */
_wcsicoll(const wchar_t * str1,const wchar_t * str2)67c2c66affSColin Finck INT CDECL _wcsicoll( const wchar_t* str1, const wchar_t* str2 )
68c2c66affSColin Finck {
69c2c66affSColin Finck /* FIXME: handle collates */
70c2c66affSColin Finck return strcmpiW( str1, str2 );
71c2c66affSColin Finck }
72c2c66affSColin Finck #endif
73c2c66affSColin Finck
74c2c66affSColin Finck /*********************************************************************
75c2c66affSColin Finck * _wcsnset (MSVCRT.@)
76c2c66affSColin Finck */
_wcsnset(wchar_t * str,wchar_t c,size_t n)77c2c66affSColin Finck wchar_t* CDECL _wcsnset( wchar_t* str, wchar_t c, size_t n )
78c2c66affSColin Finck {
79c2c66affSColin Finck wchar_t* ret = str;
80c2c66affSColin Finck while ((n-- > 0) && *str) *str++ = c;
81c2c66affSColin Finck return ret;
82c2c66affSColin Finck }
83c2c66affSColin Finck
84c2c66affSColin Finck /*********************************************************************
85c2c66affSColin Finck * _wcsrev (MSVCRT.@)
86c2c66affSColin Finck */
_wcsrev(wchar_t * str)87c2c66affSColin Finck wchar_t* CDECL _wcsrev( wchar_t* str )
88c2c66affSColin Finck {
89c2c66affSColin Finck wchar_t* ret = str;
90c2c66affSColin Finck wchar_t* end = str + strlenW(str) - 1;
91c2c66affSColin Finck while (end > str)
92c2c66affSColin Finck {
93c2c66affSColin Finck wchar_t t = *end;
94c2c66affSColin Finck *end-- = *str;
95c2c66affSColin Finck *str++ = t;
96c2c66affSColin Finck }
97c2c66affSColin Finck return ret;
98c2c66affSColin Finck }
99c2c66affSColin Finck
100c2c66affSColin Finck #ifndef _LIBCNT_
101c2c66affSColin Finck /*********************************************************************
102c2c66affSColin Finck * _wcsset (MSVCRT.@)
103c2c66affSColin Finck */
_wcsset(wchar_t * str,wchar_t c)104c2c66affSColin Finck wchar_t* CDECL _wcsset( wchar_t* str, wchar_t c )
105c2c66affSColin Finck {
106c2c66affSColin Finck wchar_t* ret = str;
107c2c66affSColin Finck while (*str) *str++ = c;
108c2c66affSColin Finck return ret;
109c2c66affSColin Finck }
110c2c66affSColin Finck
111c2c66affSColin Finck /******************************************************************
112c2c66affSColin Finck * _wcsupr_s (MSVCRT.@)
113c2c66affSColin Finck *
114c2c66affSColin Finck */
_wcsupr_s(wchar_t * str,size_t n)115c2c66affSColin Finck INT CDECL _wcsupr_s( wchar_t* str, size_t n )
116c2c66affSColin Finck {
117c2c66affSColin Finck wchar_t* ptr = str;
118c2c66affSColin Finck
119c2c66affSColin Finck if (!str || !n)
120c2c66affSColin Finck {
121c2c66affSColin Finck if (str) *str = '\0';
122c2c66affSColin Finck _set_errno(EINVAL);
123c2c66affSColin Finck return EINVAL;
124c2c66affSColin Finck }
125c2c66affSColin Finck
126c2c66affSColin Finck while (n--)
127c2c66affSColin Finck {
128c2c66affSColin Finck if (!*ptr) return 0;
129c2c66affSColin Finck *ptr = toupperW(*ptr);
130c2c66affSColin Finck ptr++;
131c2c66affSColin Finck }
132c2c66affSColin Finck
133c2c66affSColin Finck /* MSDN claims that the function should return and set errno to
134c2c66affSColin Finck * ERANGE, which doesn't seem to be true based on the tests. */
135c2c66affSColin Finck *str = '\0';
136c2c66affSColin Finck _set_errno(EINVAL);
137c2c66affSColin Finck return EINVAL;
138c2c66affSColin Finck }
139c2c66affSColin Finck
140c2c66affSColin Finck /*********************************************************************
141c2c66affSColin Finck * wcstod (MSVCRT.@)
142c2c66affSColin Finck */
wcstod(const wchar_t * lpszStr,wchar_t ** end)143c2c66affSColin Finck double CDECL wcstod(const wchar_t* lpszStr, wchar_t** end)
144c2c66affSColin Finck {
145c2c66affSColin Finck const wchar_t* str = lpszStr;
146c2c66affSColin Finck int negative = 0;
147c2c66affSColin Finck double ret = 0, divisor = 10.0;
148c2c66affSColin Finck
149c2c66affSColin Finck TRACE("(%s,%p) semi-stub\n", debugstr_w(lpszStr), end);
150c2c66affSColin Finck
151c2c66affSColin Finck /* FIXME:
152c2c66affSColin Finck * - Should set errno on failure
153c2c66affSColin Finck * - Should fail on overflow
154c2c66affSColin Finck * - Need to check which input formats are allowed
155c2c66affSColin Finck */
156c2c66affSColin Finck while (isspaceW(*str))
157c2c66affSColin Finck str++;
158c2c66affSColin Finck
159c2c66affSColin Finck if (*str == '-')
160c2c66affSColin Finck {
161c2c66affSColin Finck negative = 1;
162c2c66affSColin Finck str++;
163c2c66affSColin Finck }
164c2c66affSColin Finck
165c2c66affSColin Finck while (isdigitW(*str))
166c2c66affSColin Finck {
167c2c66affSColin Finck ret = ret * 10.0 + (*str - '0');
168c2c66affSColin Finck str++;
169c2c66affSColin Finck }
170c2c66affSColin Finck if (*str == '.')
171c2c66affSColin Finck str++;
172c2c66affSColin Finck while (isdigitW(*str))
173c2c66affSColin Finck {
174c2c66affSColin Finck ret = ret + (*str - '0') / divisor;
175c2c66affSColin Finck divisor *= 10;
176c2c66affSColin Finck str++;
177c2c66affSColin Finck }
178c2c66affSColin Finck
179c2c66affSColin Finck if (*str == 'E' || *str == 'e' || *str == 'D' || *str == 'd')
180c2c66affSColin Finck {
181c2c66affSColin Finck int negativeExponent = 0;
182c2c66affSColin Finck int exponent = 0;
183c2c66affSColin Finck if (*(++str) == '-')
184c2c66affSColin Finck {
185c2c66affSColin Finck negativeExponent = 1;
186c2c66affSColin Finck str++;
187c2c66affSColin Finck }
188c2c66affSColin Finck while (isdigitW(*str))
189c2c66affSColin Finck {
190c2c66affSColin Finck exponent = exponent * 10 + (*str - '0');
191c2c66affSColin Finck str++;
192c2c66affSColin Finck }
193c2c66affSColin Finck if (exponent != 0)
194c2c66affSColin Finck {
195c2c66affSColin Finck if (negativeExponent)
196c2c66affSColin Finck ret = ret / pow(10.0, exponent);
197c2c66affSColin Finck else
198c2c66affSColin Finck ret = ret * pow(10.0, exponent);
199c2c66affSColin Finck }
200c2c66affSColin Finck }
201c2c66affSColin Finck
202c2c66affSColin Finck if (negative)
203c2c66affSColin Finck ret = -ret;
204c2c66affSColin Finck
205c2c66affSColin Finck if (end)
206c2c66affSColin Finck *end = (wchar_t*)str;
207c2c66affSColin Finck
208c2c66affSColin Finck TRACE("returning %g\n", ret);
209c2c66affSColin Finck return ret;
210c2c66affSColin Finck }
211c2c66affSColin Finck #endif
212c2c66affSColin Finck
213c2c66affSColin Finck /*********************************************************************
214c2c66affSColin Finck * wcscoll (MSVCRT.@)
215c2c66affSColin Finck */
wcscoll(const wchar_t * str1,const wchar_t * str2)216c2c66affSColin Finck int CDECL wcscoll( const wchar_t* str1, const wchar_t* str2 )
217c2c66affSColin Finck {
218c2c66affSColin Finck /* FIXME: handle collates */
219c2c66affSColin Finck return strcmpW( str1, str2 );
220c2c66affSColin Finck }
221c2c66affSColin Finck
222c2c66affSColin Finck /*********************************************************************
223c2c66affSColin Finck * wcspbrk (MSVCRT.@)
224c2c66affSColin Finck */
wcspbrk(const wchar_t * str,const wchar_t * accept)225c2c66affSColin Finck wchar_t* CDECL wcspbrk( const wchar_t* str, const wchar_t* accept )
226c2c66affSColin Finck {
227c2c66affSColin Finck const wchar_t* p;
228c2c66affSColin Finck while (*str)
229c2c66affSColin Finck {
230c2c66affSColin Finck for (p = accept; *p; p++) if (*p == *str) return (wchar_t*)str;
231c2c66affSColin Finck str++;
232c2c66affSColin Finck }
233c2c66affSColin Finck return NULL;
234c2c66affSColin Finck }
235c2c66affSColin Finck
236c2c66affSColin Finck #ifndef _LIBCNT_
237c2c66affSColin Finck
238c2c66affSColin Finck /*********************************************************************
239c2c66affSColin Finck * wctomb (MSVCRT.@)
240c2c66affSColin Finck */
241c2c66affSColin Finck /*********************************************************************
242c2c66affSColin Finck * wctomb (MSVCRT.@)
243c2c66affSColin Finck */
wctomb(char * dst,wchar_t ch)244c2c66affSColin Finck INT CDECL wctomb( char *dst, wchar_t ch )
245c2c66affSColin Finck {
246c2c66affSColin Finck BOOL error;
247c2c66affSColin Finck INT size;
248c2c66affSColin Finck
249c2c66affSColin Finck size = WideCharToMultiByte(get_locinfo()->lc_codepage, 0, &ch, 1, dst, dst ? 6 : 0, NULL, &error);
250c2c66affSColin Finck if(!size || error) {
251c2c66affSColin Finck *_errno() = EINVAL;
252c2c66affSColin Finck return EOF;
253c2c66affSColin Finck }
254c2c66affSColin Finck return size;
255c2c66affSColin Finck }
256c2c66affSColin Finck
257c2c66affSColin Finck /*********************************************************************
258c2c66affSColin Finck * wcsrtombs_l (INTERNAL)
259c2c66affSColin Finck */
wcsrtombs_l(char * mbstr,const wchar_t ** wcstr,size_t count,_locale_t locale)260*d8eeb31bSBișoc George static size_t CDECL wcsrtombs_l(char *mbstr, const wchar_t **wcstr,
261*d8eeb31bSBișoc George size_t count, _locale_t locale)
262c2c66affSColin Finck {
263c2c66affSColin Finck MSVCRT_pthreadlocinfo locinfo;
264c2c66affSColin Finck size_t tmp = 0;
265c2c66affSColin Finck BOOL used_default;
266c2c66affSColin Finck
267c2c66affSColin Finck if(!locale)
268c2c66affSColin Finck locinfo = get_locinfo();
269c2c66affSColin Finck else
270c2c66affSColin Finck locinfo = ((MSVCRT__locale_t)locale)->locinfo;
271c2c66affSColin Finck
272*d8eeb31bSBișoc George if(!locinfo->lc_codepage) {
273*d8eeb31bSBișoc George size_t i;
274*d8eeb31bSBișoc George
275*d8eeb31bSBișoc George if(!mbstr)
276*d8eeb31bSBișoc George return strlenW(*wcstr);
277*d8eeb31bSBișoc George
278*d8eeb31bSBișoc George for(i=0; i<count; i++) {
279*d8eeb31bSBișoc George if((*wcstr)[i] > 255) {
280*d8eeb31bSBișoc George _set_errno(EILSEQ);
281*d8eeb31bSBișoc George return -1;
282*d8eeb31bSBișoc George }
283*d8eeb31bSBișoc George
284*d8eeb31bSBișoc George mbstr[i] = (*wcstr)[i];
285*d8eeb31bSBișoc George if(!(*wcstr)[i]) break;
286*d8eeb31bSBișoc George }
287*d8eeb31bSBișoc George return i;
288*d8eeb31bSBișoc George }
289*d8eeb31bSBișoc George
290c2c66affSColin Finck if(!mbstr) {
291c2c66affSColin Finck tmp = WideCharToMultiByte(locinfo->lc_codepage, WC_NO_BEST_FIT_CHARS,
292*d8eeb31bSBișoc George *wcstr, -1, NULL, 0, NULL, &used_default);
293*d8eeb31bSBișoc George if(!tmp || used_default) {
294*d8eeb31bSBișoc George _set_errno(EILSEQ);
295c2c66affSColin Finck return -1;
296*d8eeb31bSBișoc George }
297*d8eeb31bSBișoc George return tmp-1;
298c2c66affSColin Finck }
299c2c66affSColin Finck
300c2c66affSColin Finck while(**wcstr) {
301c2c66affSColin Finck char buf[3];
302c2c66affSColin Finck size_t i, size;
303c2c66affSColin Finck
304c2c66affSColin Finck size = WideCharToMultiByte(locinfo->lc_codepage, WC_NO_BEST_FIT_CHARS,
305c2c66affSColin Finck *wcstr, 1, buf, 3, NULL, &used_default);
306*d8eeb31bSBișoc George if(!size || used_default) {
307*d8eeb31bSBișoc George _set_errno(EILSEQ);
308c2c66affSColin Finck return -1;
309*d8eeb31bSBișoc George }
310c2c66affSColin Finck if(tmp+size > count)
311c2c66affSColin Finck return tmp;
312c2c66affSColin Finck
313c2c66affSColin Finck for(i=0; i<size; i++)
314c2c66affSColin Finck mbstr[tmp++] = buf[i];
315c2c66affSColin Finck (*wcstr)++;
316c2c66affSColin Finck }
317c2c66affSColin Finck
318c2c66affSColin Finck if(tmp < count) {
319c2c66affSColin Finck mbstr[tmp] = '\0';
320c2c66affSColin Finck *wcstr = NULL;
321c2c66affSColin Finck }
322c2c66affSColin Finck return tmp;
323c2c66affSColin Finck }
324c2c66affSColin Finck
325c2c66affSColin Finck /*********************************************************************
326c2c66affSColin Finck * _wcstombs_l (MSVCRT.@)
327c2c66affSColin Finck */
_wcstombs_l(char * mbstr,const wchar_t * wcstr,size_t count,_locale_t locale)328c2c66affSColin Finck size_t CDECL _wcstombs_l(char *mbstr, const wchar_t *wcstr, size_t count, _locale_t locale)
329c2c66affSColin Finck {
330c2c66affSColin Finck return wcsrtombs_l(mbstr, &wcstr, count, locale);
331c2c66affSColin Finck }
332c2c66affSColin Finck
333c2c66affSColin Finck /*********************************************************************
334c2c66affSColin Finck * wcstombs (MSVCRT.@)
335c2c66affSColin Finck */
wcstombs(char * mbstr,const wchar_t * wcstr,size_t count)336c2c66affSColin Finck size_t CDECL wcstombs(char *mbstr, const wchar_t *wcstr, size_t count)
337c2c66affSColin Finck {
338c2c66affSColin Finck return wcsrtombs_l(mbstr, &wcstr, count, NULL);
339c2c66affSColin Finck }
340c2c66affSColin Finck #endif
341c2c66affSColin Finck
342c2c66affSColin Finck /*********************************************************************
343c2c66affSColin Finck * wcscpy_s (MSVCRT.@)
344c2c66affSColin Finck */
wcscpy_s(wchar_t * wcDest,size_t numElement,const wchar_t * wcSrc)345c2c66affSColin Finck INT CDECL wcscpy_s( wchar_t* wcDest, size_t numElement, const wchar_t *wcSrc)
346c2c66affSColin Finck {
347c2c66affSColin Finck size_t size = 0;
348c2c66affSColin Finck
349c2c66affSColin Finck if(!wcDest || !numElement)
350c2c66affSColin Finck return EINVAL;
351c2c66affSColin Finck
352c2c66affSColin Finck wcDest[0] = 0;
353c2c66affSColin Finck
354c2c66affSColin Finck if(!wcSrc)
355c2c66affSColin Finck {
356c2c66affSColin Finck return EINVAL;
357c2c66affSColin Finck }
358c2c66affSColin Finck
359c2c66affSColin Finck size = strlenW(wcSrc) + 1;
360c2c66affSColin Finck
361c2c66affSColin Finck if(size > numElement)
362c2c66affSColin Finck {
363c2c66affSColin Finck return ERANGE;
364c2c66affSColin Finck }
365c2c66affSColin Finck
366c2c66affSColin Finck memcpy( wcDest, wcSrc, size*sizeof(WCHAR) );
367c2c66affSColin Finck
368c2c66affSColin Finck return 0;
369c2c66affSColin Finck }
370c2c66affSColin Finck
371c2c66affSColin Finck /******************************************************************
372c2c66affSColin Finck * wcsncpy_s (MSVCRT.@)
373c2c66affSColin Finck */
wcsncpy_s(wchar_t * wcDest,size_t numElement,const wchar_t * wcSrc,size_t count)374c2c66affSColin Finck INT CDECL wcsncpy_s( wchar_t* wcDest, size_t numElement, const wchar_t *wcSrc,
375c2c66affSColin Finck size_t count )
376c2c66affSColin Finck {
377c2c66affSColin Finck size_t size = 0;
378c2c66affSColin Finck
379c2c66affSColin Finck if (!wcDest || !numElement)
380c2c66affSColin Finck return EINVAL;
381c2c66affSColin Finck
382c2c66affSColin Finck wcDest[0] = 0;
383c2c66affSColin Finck
384c2c66affSColin Finck if (!wcSrc)
385c2c66affSColin Finck {
386c2c66affSColin Finck return EINVAL;
387c2c66affSColin Finck }
388c2c66affSColin Finck
389c2c66affSColin Finck size = min(strlenW(wcSrc), count);
390c2c66affSColin Finck
391c2c66affSColin Finck if (size >= numElement)
392c2c66affSColin Finck {
393c2c66affSColin Finck return ERANGE;
394c2c66affSColin Finck }
395c2c66affSColin Finck
396c2c66affSColin Finck memcpy( wcDest, wcSrc, size*sizeof(WCHAR) );
397c2c66affSColin Finck wcDest[size] = '\0';
398c2c66affSColin Finck
399c2c66affSColin Finck return 0;
400c2c66affSColin Finck }
401c2c66affSColin Finck
402c2c66affSColin Finck /******************************************************************
403c2c66affSColin Finck * wcscat_s (MSVCRT.@)
404c2c66affSColin Finck *
405c2c66affSColin Finck */
wcscat_s(wchar_t * dst,size_t elem,const wchar_t * src)406c2c66affSColin Finck INT CDECL wcscat_s(wchar_t* dst, size_t elem, const wchar_t* src)
407c2c66affSColin Finck {
408c2c66affSColin Finck wchar_t* ptr = dst;
409c2c66affSColin Finck
410c2c66affSColin Finck if (!dst || elem == 0) return EINVAL;
411c2c66affSColin Finck if (!src)
412c2c66affSColin Finck {
413c2c66affSColin Finck dst[0] = '\0';
414c2c66affSColin Finck return EINVAL;
415c2c66affSColin Finck }
416c2c66affSColin Finck
417c2c66affSColin Finck /* seek to end of dst string (or elem if no end of string is found */
418c2c66affSColin Finck while (ptr < dst + elem && *ptr != '\0') ptr++;
419c2c66affSColin Finck while (ptr < dst + elem)
420c2c66affSColin Finck {
421c2c66affSColin Finck if ((*ptr++ = *src++) == '\0') return 0;
422c2c66affSColin Finck }
423c2c66affSColin Finck /* not enough space */
424c2c66affSColin Finck dst[0] = '\0';
425c2c66affSColin Finck return ERANGE;
426c2c66affSColin Finck }
427c2c66affSColin Finck
428c2c66affSColin Finck /*********************************************************************
429c2c66affSColin Finck * wcsncat_s (MSVCRT.@)
430c2c66affSColin Finck *
431c2c66affSColin Finck */
wcsncat_s(wchar_t * dst,size_t elem,const wchar_t * src,size_t count)432c2c66affSColin Finck INT CDECL wcsncat_s(wchar_t *dst, size_t elem,
433c2c66affSColin Finck const wchar_t *src, size_t count)
434c2c66affSColin Finck {
435c2c66affSColin Finck size_t srclen;
436c2c66affSColin Finck wchar_t dststart;
437c2c66affSColin Finck INT ret = 0;
438c2c66affSColin Finck
439c2c66affSColin Finck if (!MSVCRT_CHECK_PMT(dst != NULL) || !MSVCRT_CHECK_PMT(elem > 0))
440c2c66affSColin Finck {
441c2c66affSColin Finck #ifndef _LIBCNT_
442c2c66affSColin Finck _set_errno(EINVAL);
443c2c66affSColin Finck #endif
444c2c66affSColin Finck return EINVAL;
445c2c66affSColin Finck }
446c2c66affSColin Finck if (!MSVCRT_CHECK_PMT(src != NULL || count == 0))
447c2c66affSColin Finck return EINVAL;
448c2c66affSColin Finck if (count == 0)
449c2c66affSColin Finck return 0;
450c2c66affSColin Finck
451c2c66affSColin Finck for (dststart = 0; dststart < elem; dststart++)
452c2c66affSColin Finck {
453c2c66affSColin Finck if (dst[dststart] == '\0')
454c2c66affSColin Finck break;
455c2c66affSColin Finck }
456c2c66affSColin Finck if (dststart == elem)
457c2c66affSColin Finck {
458c2c66affSColin Finck MSVCRT_INVALID_PMT("dst[elem] is not NULL terminated\n", EINVAL);
459c2c66affSColin Finck return EINVAL;
460c2c66affSColin Finck }
461c2c66affSColin Finck
462c2c66affSColin Finck if (count == _TRUNCATE)
463c2c66affSColin Finck {
464c2c66affSColin Finck srclen = strlenW(src);
465c2c66affSColin Finck if (srclen >= (elem - dststart))
466c2c66affSColin Finck {
467c2c66affSColin Finck srclen = elem - dststart - 1;
468c2c66affSColin Finck ret = STRUNCATE;
469c2c66affSColin Finck }
470c2c66affSColin Finck }
471c2c66affSColin Finck else
472c2c66affSColin Finck srclen = min(strlenW(src), count);
473c2c66affSColin Finck if (srclen < (elem - dststart))
474c2c66affSColin Finck {
475c2c66affSColin Finck memcpy(&dst[dststart], src, srclen*sizeof(wchar_t));
476c2c66affSColin Finck dst[dststart+srclen] = '\0';
477c2c66affSColin Finck return ret;
478c2c66affSColin Finck }
479c2c66affSColin Finck MSVCRT_INVALID_PMT("dst[elem] is too small", ERANGE);
480c2c66affSColin Finck dst[0] = '\0';
481c2c66affSColin Finck return ERANGE;
482c2c66affSColin Finck }
483c2c66affSColin Finck
484