xref: /reactos/sdk/lib/crt/string/wcs.c (revision d8eeb31b)
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