makefiles: Don't use standard libs for programs that specify -nodefaultlibs.
[wine/zf.git] / dlls / msvcrt / wcs.c
blob17d06eed3c2b7cdc25f1489a117e0a405625ec2e
1 /*
2 * msvcrt.dll wide-char functions
4 * Copyright 1999 Alexandre Julliard
5 * Copyright 2000 Jon Griffiths
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include <limits.h>
25 #include <stdio.h>
26 #include <math.h>
27 #include <assert.h>
28 #include "msvcrt.h"
29 #include "winnls.h"
30 #include "wtypes.h"
31 #include "wine/unicode.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
36 static BOOL n_format_enabled = TRUE;
38 #include "printf.h"
39 #define PRINTF_WIDE
40 #include "printf.h"
41 #undef PRINTF_WIDE
43 #if _MSVCR_VER>=80
45 /*********************************************************************
46 * _get_printf_count_output (MSVCR80.@)
48 int CDECL MSVCRT__get_printf_count_output( void )
50 return n_format_enabled ? 1 : 0;
53 /*********************************************************************
54 * _set_printf_count_output (MSVCR80.@)
56 int CDECL MSVCRT__set_printf_count_output( int enable )
58 BOOL old = n_format_enabled;
59 n_format_enabled = enable != 0;
60 return old ? 1 : 0;
63 #endif /* _MSVCR_VER>=80 */
65 /*********************************************************************
66 * _wcsdup (MSVCRT.@)
68 MSVCRT_wchar_t* CDECL MSVCRT__wcsdup( const MSVCRT_wchar_t* str )
70 MSVCRT_wchar_t* ret = NULL;
71 if (str)
73 int size = (strlenW(str) + 1) * sizeof(MSVCRT_wchar_t);
74 ret = MSVCRT_malloc( size );
75 if (ret) memcpy( ret, str, size );
77 return ret;
80 INT CDECL MSVCRT__wcsicmp_l(const MSVCRT_wchar_t *str1, const MSVCRT_wchar_t *str2, MSVCRT__locale_t locale)
82 if(!MSVCRT_CHECK_PMT(str1 != NULL) || !MSVCRT_CHECK_PMT(str2 != NULL))
83 return MSVCRT__NLSCMPERROR;
85 return strcmpiW(str1, str2);
88 /*********************************************************************
89 * _wcsicmp (MSVCRT.@)
91 INT CDECL MSVCRT__wcsicmp( const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2 )
93 return strcmpiW( str1, str2 );
96 /*********************************************************************
97 * _wcsnicmp_l (MSVCRT.@)
99 INT CDECL MSVCRT__wcsnicmp_l(const MSVCRT_wchar_t *str1, const MSVCRT_wchar_t *str2, INT n, MSVCRT__locale_t locale)
101 return strncmpiW(str1, str2, n);
104 /*********************************************************************
105 * _wcsnicmp (MSVCRT.@)
107 INT CDECL MSVCRT__wcsnicmp(const MSVCRT_wchar_t *str1, const MSVCRT_wchar_t *str2, INT n)
109 return MSVCRT__wcsnicmp_l(str1, str2, n, NULL);
112 /*********************************************************************
113 * _wcsicoll_l (MSVCRT.@)
115 int CDECL MSVCRT__wcsicoll_l(const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2, MSVCRT__locale_t locale)
117 MSVCRT_pthreadlocinfo locinfo;
119 if(!locale)
120 locinfo = get_locinfo();
121 else
122 locinfo = locale->locinfo;
124 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE])
125 return strcmpiW(str1, str2);
126 return CompareStringW(locinfo->lc_handle[MSVCRT_LC_COLLATE], NORM_IGNORECASE,
127 str1, -1, str2, -1)-CSTR_EQUAL;
130 /*********************************************************************
131 * _wcsicoll (MSVCRT.@)
133 INT CDECL MSVCRT__wcsicoll( const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2 )
135 return MSVCRT__wcsicoll_l(str1, str2, NULL);
138 /*********************************************************************
139 * _wcsnicoll_l (MSVCRT.@)
141 int CDECL MSVCRT__wcsnicoll_l(const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2,
142 MSVCRT_size_t count, MSVCRT__locale_t locale)
144 MSVCRT_pthreadlocinfo locinfo;
146 if(!locale)
147 locinfo = get_locinfo();
148 else
149 locinfo = locale->locinfo;
151 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE])
152 return strncmpiW(str1, str2, count);
153 return CompareStringW(locinfo->lc_handle[MSVCRT_LC_COLLATE], NORM_IGNORECASE,
154 str1, MSVCRT_wcsnlen(str1, count),
155 str2, MSVCRT_wcsnlen(str2, count))-CSTR_EQUAL;
158 /*********************************************************************
159 * _wcsnicoll (MSVCRT.@)
161 INT CDECL MSVCRT__wcsnicoll( const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2, MSVCRT_size_t count )
163 return MSVCRT__wcsnicoll_l(str1, str2, count, NULL);
166 /*********************************************************************
167 * _wcsnset (MSVCRT.@)
169 MSVCRT_wchar_t* CDECL MSVCRT__wcsnset( MSVCRT_wchar_t* str, MSVCRT_wchar_t c, MSVCRT_size_t n )
171 MSVCRT_wchar_t* ret = str;
172 while ((n-- > 0) && *str) *str++ = c;
173 return ret;
176 /*********************************************************************
177 * _wcsnset_s (MSVCRT.@)
179 int CDECL MSVCRT__wcsnset_s( MSVCRT_wchar_t *str, MSVCRT_size_t size, MSVCRT_wchar_t c, MSVCRT_size_t count )
181 MSVCRT_size_t i;
183 if(!str && !size && !count) return 0;
184 if(!MSVCRT_CHECK_PMT(str != NULL)) return MSVCRT_EINVAL;
185 if(!MSVCRT_CHECK_PMT(size > 0)) return MSVCRT_EINVAL;
187 for(i=0; i<size-1 && i<count; i++) {
188 if(!str[i]) return 0;
189 str[i] = c;
191 for(; i<size; i++)
192 if(!str[i]) return 0;
194 str[0] = 0;
195 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
196 *MSVCRT__errno() = MSVCRT_EINVAL;
197 return MSVCRT_EINVAL;
200 /*********************************************************************
201 * _wcsrev (MSVCRT.@)
203 MSVCRT_wchar_t* CDECL MSVCRT__wcsrev( MSVCRT_wchar_t* str )
205 MSVCRT_wchar_t* ret = str;
206 MSVCRT_wchar_t* end = str + strlenW(str) - 1;
207 while (end > str)
209 MSVCRT_wchar_t t = *end;
210 *end-- = *str;
211 *str++ = t;
213 return ret;
216 /*********************************************************************
217 * _wcsset_s (MSVCRT.@)
219 int CDECL MSVCRT__wcsset_s( MSVCRT_wchar_t *str, MSVCRT_size_t n, MSVCRT_wchar_t c )
221 MSVCRT_wchar_t *p = str;
223 if(!MSVCRT_CHECK_PMT(str != NULL)) return MSVCRT_EINVAL;
224 if(!MSVCRT_CHECK_PMT(n)) return MSVCRT_EINVAL;
226 while(*p && --n) *p++ = c;
227 if(!n) {
228 str[0] = 0;
229 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
230 *MSVCRT__errno() = MSVCRT_EINVAL;
231 return MSVCRT_EINVAL;
233 return 0;
236 /*********************************************************************
237 * _wcsset (MSVCRT.@)
239 MSVCRT_wchar_t* CDECL MSVCRT__wcsset( MSVCRT_wchar_t* str, MSVCRT_wchar_t c )
241 MSVCRT_wchar_t* ret = str;
242 while (*str) *str++ = c;
243 return ret;
246 /******************************************************************
247 * _wcsupr_s_l (MSVCRT.@)
249 int CDECL MSVCRT__wcsupr_s_l( MSVCRT_wchar_t* str, MSVCRT_size_t n,
250 MSVCRT__locale_t locale )
252 MSVCRT_wchar_t* ptr = str;
254 if (!str || !n)
256 if (str) *str = '\0';
257 *MSVCRT__errno() = MSVCRT_EINVAL;
258 return MSVCRT_EINVAL;
261 while (n--)
263 if (!*ptr) return 0;
264 /* FIXME: add locale support */
265 *ptr = toupperW(*ptr);
266 ptr++;
269 /* MSDN claims that the function should return and set errno to
270 * ERANGE, which doesn't seem to be true based on the tests. */
271 *str = '\0';
272 *MSVCRT__errno() = MSVCRT_EINVAL;
273 return MSVCRT_EINVAL;
276 /******************************************************************
277 * _wcsupr_s (MSVCRT.@)
280 INT CDECL MSVCRT__wcsupr_s( MSVCRT_wchar_t* str, MSVCRT_size_t n )
282 return MSVCRT__wcsupr_s_l( str, n, NULL );
285 /******************************************************************
286 * _wcsupr_l (MSVCRT.@)
288 MSVCRT_wchar_t* CDECL MSVCRT__wcsupr_l( MSVCRT_wchar_t *str, MSVCRT__locale_t locale )
290 MSVCRT__wcsupr_s_l( str, -1, locale);
291 return str;
294 /******************************************************************
295 * _wcsupr (MSVCRT.@)
297 MSVCRT_wchar_t* CDECL MSVCRT__wcsupr( MSVCRT_wchar_t *str )
299 return MSVCRT__wcsupr_l(str, NULL);
302 /******************************************************************
303 * _wcslwr_s_l (MSVCRT.@)
305 int CDECL MSVCRT__wcslwr_s_l( MSVCRT_wchar_t* str, MSVCRT_size_t n, MSVCRT__locale_t locale )
307 MSVCRT_wchar_t* ptr = str;
309 if (!str || !n)
311 if (str) *str = '\0';
312 *MSVCRT__errno() = MSVCRT_EINVAL;
313 return MSVCRT_EINVAL;
316 while (n--)
318 if (!*ptr) return 0;
319 *ptr = tolowerW(*ptr);
320 ptr++;
323 /* MSDN claims that the function should return and set errno to
324 * ERANGE, which doesn't seem to be true based on the tests. */
325 *str = '\0';
326 *MSVCRT__errno() = MSVCRT_EINVAL;
327 return MSVCRT_EINVAL;
330 /******************************************************************
331 * _wcslwr_s (MSVCRT.@)
333 int CDECL MSVCRT__wcslwr_s( MSVCRT_wchar_t* str, MSVCRT_size_t n )
335 return MSVCRT__wcslwr_s_l(str, n, NULL);
338 /******************************************************************
339 * _wcslwr_l (MSVCRT.@)
341 MSVCRT_wchar_t* CDECL MSVCRT__wcslwr_l( MSVCRT_wchar_t* str, MSVCRT__locale_t locale )
343 MSVCRT__wcslwr_s_l(str, -1, locale);
344 return str;
347 /******************************************************************
348 * _wcslwr (MSVCRT.@)
350 MSVCRT_wchar_t* CDECL MSVCRT__wcslwr( MSVCRT_wchar_t* str )
352 MSVCRT__wcslwr_s_l(str, -1, NULL);
353 return str;
356 /*********************************************************************
357 * _wcsncoll_l (MSVCRT.@)
359 int CDECL MSVCRT__wcsncoll_l(const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2,
360 MSVCRT_size_t count, MSVCRT__locale_t locale)
362 MSVCRT_pthreadlocinfo locinfo;
364 if(!locale)
365 locinfo = get_locinfo();
366 else
367 locinfo = locale->locinfo;
369 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE])
370 return strncmpW(str1, str2, count);
371 return CompareStringW(locinfo->lc_handle[MSVCRT_LC_COLLATE], 0,
372 str1, MSVCRT_wcsnlen(str1, count),
373 str2, MSVCRT_wcsnlen(str2, count))-CSTR_EQUAL;
376 /*********************************************************************
377 * _wcsncoll (MSVCRT.@)
379 int CDECL MSVCRT__wcsncoll(const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2, MSVCRT_size_t count)
381 return MSVCRT__wcsncoll_l(str1, str2, count, NULL);
384 static MSVCRT_wchar_t strtod_wstr_get(void *ctx)
386 const MSVCRT_wchar_t **p = ctx;
387 if (!**p) return MSVCRT_WEOF;
388 return *(*p)++;
391 static void strtod_wstr_unget(void *ctx)
393 const MSVCRT_wchar_t **p = ctx;
394 (*p)--;
397 /*********************************************************************
398 * _wcstod_l (MSVCRT.@)
400 double CDECL MSVCRT__wcstod_l(const MSVCRT_wchar_t* str, MSVCRT_wchar_t** end,
401 MSVCRT__locale_t locale)
403 MSVCRT_pthreadlocinfo locinfo;
404 const MSVCRT_wchar_t *beg, *p;
405 double ret;
407 if (!MSVCRT_CHECK_PMT(str != NULL)) {
408 if (end) *end = NULL;
409 return 0;
412 if (!locale)
413 locinfo = get_locinfo();
414 else
415 locinfo = locale->locinfo;
417 p = str;
418 while(MSVCRT__iswspace_l(*p, locale))
419 p++;
420 beg = p;
422 ret = parse_double(strtod_wstr_get, strtod_wstr_unget, &p, locinfo, NULL);
423 if (end) *end = (p == beg ? (MSVCRT_wchar_t*)str : (MSVCRT_wchar_t*)p);
424 return ret;
427 /*********************************************************************
428 * wcsrtombs_l (INTERNAL)
430 static MSVCRT_size_t MSVCRT_wcsrtombs_l(char *mbstr, const MSVCRT_wchar_t **wcstr,
431 MSVCRT_size_t count, MSVCRT__locale_t locale)
433 MSVCRT_pthreadlocinfo locinfo;
434 MSVCRT_size_t tmp = 0;
435 BOOL used_default;
437 if(!locale)
438 locinfo = get_locinfo();
439 else
440 locinfo = locale->locinfo;
442 if(!locinfo->lc_codepage) {
443 MSVCRT_size_t i;
445 if(!mbstr)
446 return strlenW(*wcstr);
448 for(i=0; i<count; i++) {
449 if((*wcstr)[i] > 255) {
450 *MSVCRT__errno() = MSVCRT_EILSEQ;
451 return -1;
454 mbstr[i] = (*wcstr)[i];
455 if(!(*wcstr)[i]) break;
457 return i;
460 if(!mbstr) {
461 tmp = WideCharToMultiByte(locinfo->lc_codepage, WC_NO_BEST_FIT_CHARS,
462 *wcstr, -1, NULL, 0, NULL, &used_default);
463 if(!tmp || used_default) {
464 *MSVCRT__errno() = MSVCRT_EILSEQ;
465 return -1;
467 return tmp-1;
470 while(**wcstr) {
471 char buf[3];
472 MSVCRT_size_t i, size;
474 size = WideCharToMultiByte(locinfo->lc_codepage, WC_NO_BEST_FIT_CHARS,
475 *wcstr, 1, buf, 3, NULL, &used_default);
476 if(!size || used_default) {
477 *MSVCRT__errno() = MSVCRT_EILSEQ;
478 return -1;
480 if(tmp+size > count)
481 return tmp;
483 for(i=0; i<size; i++)
484 mbstr[tmp++] = buf[i];
485 (*wcstr)++;
488 if(tmp < count) {
489 mbstr[tmp] = '\0';
490 *wcstr = NULL;
492 return tmp;
495 /*********************************************************************
496 * _wcstombs_l (MSVCRT.@)
498 MSVCRT_size_t CDECL MSVCRT__wcstombs_l(char *mbstr, const MSVCRT_wchar_t *wcstr,
499 MSVCRT_size_t count, MSVCRT__locale_t locale)
501 return MSVCRT_wcsrtombs_l(mbstr, &wcstr, count, locale);
504 /*********************************************************************
505 * wcstombs (MSVCRT.@)
507 MSVCRT_size_t CDECL MSVCRT_wcstombs(char *mbstr, const MSVCRT_wchar_t *wcstr,
508 MSVCRT_size_t count)
510 return MSVCRT_wcsrtombs_l(mbstr, &wcstr, count, NULL);
513 /*********************************************************************
514 * wcsrtombs (MSVCRT.@)
516 MSVCRT_size_t CDECL MSVCRT_wcsrtombs(char *mbstr, const MSVCRT_wchar_t **wcstr,
517 MSVCRT_size_t count, MSVCRT_mbstate_t *mbstate)
519 if(mbstate)
520 *mbstate = 0;
522 return MSVCRT_wcsrtombs_l(mbstr, wcstr, count, NULL);
525 /*********************************************************************
526 * MSVCRT_wcsrtombs_s_l (INTERNAL)
528 static int MSVCRT_wcsrtombs_s_l(MSVCRT_size_t *ret, char *mbstr,
529 MSVCRT_size_t size, const MSVCRT_wchar_t **wcstr,
530 MSVCRT_size_t count, MSVCRT__locale_t locale)
532 MSVCRT_size_t conv;
533 int err;
535 if(!mbstr && !size && wcstr) {
536 conv = MSVCRT_wcsrtombs_l(NULL, wcstr, 0, locale);
537 if(ret)
538 *ret = conv+1;
539 if(conv == -1)
540 return *MSVCRT__errno();
541 return 0;
544 if (!MSVCRT_CHECK_PMT(mbstr != NULL)) return MSVCRT_EINVAL;
545 if (size) mbstr[0] = '\0';
546 if (!MSVCRT_CHECK_PMT(wcstr != NULL)) return MSVCRT_EINVAL;
547 if (!MSVCRT_CHECK_PMT(*wcstr != NULL)) return MSVCRT_EINVAL;
549 if(count==MSVCRT__TRUNCATE || size<count)
550 conv = size;
551 else
552 conv = count;
554 err = 0;
555 conv = MSVCRT_wcsrtombs_l(mbstr, wcstr, conv, locale);
556 if(conv == -1) {
557 conv = 0;
558 if(size)
559 mbstr[0] = '\0';
560 err = *MSVCRT__errno();
561 }else if(conv < size)
562 mbstr[conv++] = '\0';
563 else if(conv==size && (count==MSVCRT__TRUNCATE || mbstr[conv-1]=='\0')) {
564 mbstr[conv-1] = '\0';
565 if(count==MSVCRT__TRUNCATE)
566 err = MSVCRT_STRUNCATE;
567 }else {
568 MSVCRT_INVALID_PMT("mbstr[size] is too small", MSVCRT_ERANGE);
569 conv = 0;
570 if(size)
571 mbstr[0] = '\0';
572 err = MSVCRT_ERANGE;
575 if(ret)
576 *ret = conv;
577 return err;
580 /*********************************************************************
581 * _wcstombs_s_l (MSVCRT.@)
583 int CDECL MSVCRT__wcstombs_s_l(MSVCRT_size_t *ret, char *mbstr,
584 MSVCRT_size_t size, const MSVCRT_wchar_t *wcstr,
585 MSVCRT_size_t count, MSVCRT__locale_t locale)
587 return MSVCRT_wcsrtombs_s_l(ret, mbstr, size, &wcstr,count, locale);
590 /*********************************************************************
591 * wcstombs_s (MSVCRT.@)
593 int CDECL MSVCRT_wcstombs_s(MSVCRT_size_t *ret, char *mbstr,
594 MSVCRT_size_t size, const MSVCRT_wchar_t *wcstr, MSVCRT_size_t count)
596 return MSVCRT_wcsrtombs_s_l(ret, mbstr, size, &wcstr, count, NULL);
599 /*********************************************************************
600 * wcsrtombs_s (MSVCRT.@)
602 int CDECL MSVCRT_wcsrtombs_s(MSVCRT_size_t *ret, char *mbstr, MSVCRT_size_t size,
603 const MSVCRT_wchar_t **wcstr, MSVCRT_size_t count, MSVCRT_mbstate_t *mbstate)
605 if(mbstate)
606 *mbstate = 0;
608 return MSVCRT_wcsrtombs_s_l(ret, mbstr, size, wcstr, count, NULL);
611 /*********************************************************************
612 * wcstod (MSVCRT.@)
614 double CDECL MSVCRT_wcstod(const MSVCRT_wchar_t* lpszStr, MSVCRT_wchar_t** end)
616 return MSVCRT__wcstod_l(lpszStr, end, NULL);
619 /*********************************************************************
620 * _wtof (MSVCRT.@)
622 double CDECL MSVCRT__wtof(const MSVCRT_wchar_t *str)
624 return MSVCRT__wcstod_l(str, NULL, NULL);
627 /*********************************************************************
628 * _wtof_l (MSVCRT.@)
630 double CDECL MSVCRT__wtof_l(const MSVCRT_wchar_t *str, MSVCRT__locale_t locale)
632 return MSVCRT__wcstod_l(str, NULL, locale);
635 #if _MSVCR_VER>=120
637 /*********************************************************************
638 * _wcstof_l (MSVCR120.@)
640 float CDECL MSVCRT__wcstof_l( const MSVCRT_wchar_t *str, MSVCRT_wchar_t **end, MSVCRT__locale_t locale )
642 return MSVCRT__wcstod_l(str, end, locale);
645 /*********************************************************************
646 * wcstof (MSVCR120.@)
648 float CDECL MSVCRT_wcstof( const MSVCRT_wchar_t *str, MSVCRT_wchar_t **end )
650 return MSVCRT__wcstof_l(str, end, NULL);
653 #endif /* _MSVCR_VER>=120 */
655 /*********************************************************************
656 * arg_clbk_valist (INTERNAL)
658 printf_arg arg_clbk_valist(void *ctx, int arg_pos, int type, __ms_va_list *valist)
660 printf_arg ret;
662 if(type == VT_I8)
663 ret.get_longlong = va_arg(*valist, LONGLONG);
664 else if(type == VT_INT)
665 ret.get_int = va_arg(*valist, int);
666 else if(type == VT_R8)
667 ret.get_double = va_arg(*valist, double);
668 else if(type == VT_PTR)
669 ret.get_ptr = va_arg(*valist, void*);
670 else {
671 ERR("Incorrect type\n");
672 ret.get_int = 0;
675 return ret;
678 /*********************************************************************
679 * arg_clbk_positional (INTERNAL)
681 printf_arg arg_clbk_positional(void *ctx, int pos, int type, __ms_va_list *valist)
683 printf_arg *args = ctx;
684 return args[pos];
687 /*********************************************************************
688 * _vsnprintf (MSVCRT.@)
690 int CDECL MSVCRT_vsnprintf( char *str, MSVCRT_size_t len,
691 const char *format, __ms_va_list valist )
693 static const char nullbyte = '\0';
694 struct _str_ctx_a ctx = {len, str};
695 int ret;
697 ret = pf_printf_a(puts_clbk_str_a, &ctx, format, NULL, 0,
698 arg_clbk_valist, NULL, &valist);
699 puts_clbk_str_a(&ctx, 1, &nullbyte);
700 return ret;
703 #if _MSVCR_VER>=140
705 static int puts_clbk_str_c99_a(void *ctx, int len, const char *str)
707 struct _str_ctx_a *out = ctx;
709 if(!out->buf)
710 return len;
712 if(out->len < len) {
713 memmove(out->buf, str, out->len);
714 out->buf += out->len;
715 out->len = 0;
716 return len;
719 memmove(out->buf, str, len);
720 out->buf += len;
721 out->len -= len;
722 return len;
725 /*********************************************************************
726 * __stdio_common_vsprintf (UCRTBASE.@)
728 int CDECL __stdio_common_vsprintf( unsigned __int64 options, char *str, MSVCRT_size_t len, const char *format,
729 MSVCRT__locale_t locale, __ms_va_list valist )
731 static const char nullbyte = '\0';
732 struct _str_ctx_a ctx = {len, str};
733 int ret;
735 if (options & ~UCRTBASE_PRINTF_MASK)
736 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
737 ret = pf_printf_a(puts_clbk_str_c99_a,
738 &ctx, format, locale, options & UCRTBASE_PRINTF_MASK, arg_clbk_valist, NULL, &valist);
739 puts_clbk_str_a(&ctx, 1, &nullbyte);
741 if(!str)
742 return ret;
743 if(options & UCRTBASE_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION)
744 return ret>len ? -1 : ret;
745 if(ret>=len) {
746 if(len) str[len-1] = 0;
747 return (options & UCRTBASE_PRINTF_STANDARD_SNPRINTF_BEHAVIOUR) ? ret : -2;
749 return ret;
752 #endif /* _MSVCR_VER>=140 */
754 /*********************************************************************
755 * _vsnprintf_l (MSVCRT.@)
757 int CDECL MSVCRT_vsnprintf_l( char *str, MSVCRT_size_t len, const char *format,
758 MSVCRT__locale_t locale, __ms_va_list valist )
760 static const char nullbyte = '\0';
761 struct _str_ctx_a ctx = {len, str};
762 int ret;
764 ret = pf_printf_a(puts_clbk_str_a, &ctx, format, locale, 0,
765 arg_clbk_valist, NULL, &valist);
766 puts_clbk_str_a(&ctx, 1, &nullbyte);
767 return ret;
770 /*********************************************************************
771 * _vsprintf_l (MSVCRT.@)
773 int CDECL MSVCRT_vsprintf_l( char *str, const char *format,
774 MSVCRT__locale_t locale, __ms_va_list valist )
776 return MSVCRT_vsnprintf_l(str, INT_MAX, format, locale, valist);
779 /*********************************************************************
780 * _sprintf_l (MSVCRT.@)
782 int WINAPIV MSVCRT_sprintf_l(char *str, const char *format,
783 MSVCRT__locale_t locale, ...)
785 int retval;
786 __ms_va_list valist;
787 __ms_va_start(valist, locale);
788 retval = MSVCRT_vsnprintf_l(str, INT_MAX, format, locale, valist);
789 __ms_va_end(valist);
790 return retval;
793 static int CDECL MSVCRT_vsnprintf_s_l_opt( char *str, MSVCRT_size_t sizeOfBuffer,
794 MSVCRT_size_t count, const char *format, DWORD options,
795 MSVCRT__locale_t locale, __ms_va_list valist )
797 static const char nullbyte = '\0';
798 struct _str_ctx_a ctx;
799 int len, ret;
801 if(sizeOfBuffer<count+1 || count==-1)
802 len = sizeOfBuffer;
803 else
804 len = count+1;
806 ctx.len = len;
807 ctx.buf = str;
808 ret = pf_printf_a(puts_clbk_str_a, &ctx, format, locale, MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
809 arg_clbk_valist, NULL, &valist);
810 puts_clbk_str_a(&ctx, 1, &nullbyte);
812 if(ret<0 || ret==len) {
813 if(count!=MSVCRT__TRUNCATE && count>sizeOfBuffer) {
814 MSVCRT_INVALID_PMT("str[sizeOfBuffer] is too small", MSVCRT_ERANGE);
815 memset(str, 0, sizeOfBuffer);
816 } else
817 str[len-1] = '\0';
819 return -1;
822 return ret;
825 static int MSVCRT_vsnwprintf_s_l_opt( MSVCRT_wchar_t *str, MSVCRT_size_t sizeOfBuffer,
826 MSVCRT_size_t count, const MSVCRT_wchar_t *format, DWORD options,
827 MSVCRT__locale_t locale, __ms_va_list valist)
829 static const MSVCRT_wchar_t nullbyte = '\0';
830 struct _str_ctx_w ctx;
831 int len, ret;
833 len = sizeOfBuffer;
834 if(count!=-1 && len>count+1)
835 len = count+1;
837 ctx.len = len;
838 ctx.buf = str;
839 ret = pf_printf_w(puts_clbk_str_w, &ctx, format, locale, MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
840 arg_clbk_valist, NULL, &valist);
841 puts_clbk_str_w(&ctx, 1, &nullbyte);
843 if(ret<0 || ret==len) {
844 if(count!=MSVCRT__TRUNCATE && count>sizeOfBuffer) {
845 MSVCRT_INVALID_PMT("str[sizeOfBuffer] is too small", MSVCRT_ERANGE);
846 memset(str, 0, sizeOfBuffer*sizeof(MSVCRT_wchar_t));
847 } else
848 str[len-1] = '\0';
850 return -1;
853 return ret;
856 /*********************************************************************
857 * _vsnprintf_s_l (MSVCRT.@)
859 int CDECL MSVCRT_vsnprintf_s_l( char *str, MSVCRT_size_t sizeOfBuffer,
860 MSVCRT_size_t count, const char *format,
861 MSVCRT__locale_t locale, __ms_va_list valist )
863 return MSVCRT_vsnprintf_s_l_opt(str, sizeOfBuffer, count, format, 0, locale, valist);
866 /*********************************************************************
867 * _vsprintf_s_l (MSVCRT.@)
869 int CDECL MSVCRT_vsprintf_s_l( char *str, MSVCRT_size_t count, const char *format,
870 MSVCRT__locale_t locale, __ms_va_list valist )
872 return MSVCRT_vsnprintf_s_l(str, INT_MAX, count, format, locale, valist);
875 /*********************************************************************
876 * _sprintf_s_l (MSVCRT.@)
878 int WINAPIV MSVCRT_sprintf_s_l( char *str, MSVCRT_size_t count, const char *format,
879 MSVCRT__locale_t locale, ...)
881 int retval;
882 __ms_va_list valist;
883 __ms_va_start(valist, locale);
884 retval = MSVCRT_vsnprintf_s_l(str, INT_MAX, count, format, locale, valist);
885 __ms_va_end(valist);
886 return retval;
889 /*********************************************************************
890 * _vsnprintf_s (MSVCRT.@)
892 int CDECL MSVCRT_vsnprintf_s( char *str, MSVCRT_size_t sizeOfBuffer,
893 MSVCRT_size_t count, const char *format, __ms_va_list valist )
895 return MSVCRT_vsnprintf_s_l(str,sizeOfBuffer, count, format, NULL, valist);
898 #if _MSVCR_VER>=140
900 /*********************************************************************
901 * __stdio_common_vsnprintf_s (UCRTBASE.@)
903 int CDECL MSVCRT__stdio_common_vsnprintf_s( unsigned __int64 options,
904 char *str, MSVCRT_size_t sizeOfBuffer, MSVCRT_size_t count,
905 const char *format, MSVCRT__locale_t locale, __ms_va_list valist )
907 if (options & ~UCRTBASE_PRINTF_MASK)
908 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
909 return MSVCRT_vsnprintf_s_l_opt(str, sizeOfBuffer, count, format, options & UCRTBASE_PRINTF_MASK, locale, valist);
912 /*********************************************************************
913 * __stdio_common_vsnwprintf_s (UCRTBASE.@)
915 int CDECL MSVCRT__stdio_common_vsnwprintf_s( unsigned __int64 options,
916 MSVCRT_wchar_t *str, MSVCRT_size_t sizeOfBuffer, MSVCRT_size_t count,
917 const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, __ms_va_list valist )
919 if (options & ~UCRTBASE_PRINTF_MASK)
920 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
921 return MSVCRT_vsnwprintf_s_l_opt(str, sizeOfBuffer, count, format, options & UCRTBASE_PRINTF_MASK, locale, valist);
924 /*********************************************************************
925 * __stdio_common_vswprintf_s (UCRTBASE.@)
927 int CDECL MSVCRT__stdio_common_vswprintf_s( unsigned __int64 options,
928 MSVCRT_wchar_t *str, MSVCRT_size_t count, const MSVCRT_wchar_t *format,
929 MSVCRT__locale_t locale, __ms_va_list valist )
931 return MSVCRT__stdio_common_vsnwprintf_s(options, str, INT_MAX, count, format, locale, valist);
934 /*********************************************************************
935 * __stdio_common_vsprintf_s (UCRTBASE.@)
937 int CDECL MSVCRT__stdio_common_vsprintf_s( unsigned __int64 options,
938 char *str, MSVCRT_size_t count, const char *format,
939 MSVCRT__locale_t locale, __ms_va_list valist )
941 if (options & ~UCRTBASE_PRINTF_MASK)
942 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
943 return MSVCRT_vsnprintf_s_l_opt(str, INT_MAX, count, format, options & UCRTBASE_PRINTF_MASK, locale, valist);
946 #endif /* _MSVCR_VER>=140 */
948 /*********************************************************************
949 * vsprintf (MSVCRT.@)
951 int CDECL MSVCRT_vsprintf( char *str, const char *format, __ms_va_list valist)
953 return MSVCRT_vsnprintf(str, INT_MAX, format, valist);
956 /*********************************************************************
957 * vsprintf_s (MSVCRT.@)
959 int CDECL MSVCRT_vsprintf_s( char *str, MSVCRT_size_t num, const char *format, __ms_va_list valist)
961 return MSVCRT_vsnprintf(str, num, format, valist);
964 /*********************************************************************
965 * _vscprintf (MSVCRT.@)
967 int CDECL MSVCRT__vscprintf( const char *format, __ms_va_list valist )
969 return MSVCRT_vsnprintf( NULL, INT_MAX, format, valist );
972 /*********************************************************************
973 * _vscprintf_l (MSVCRT.@)
975 int CDECL MSVCRT__vscprintf_l(const char *format,
976 MSVCRT__locale_t locale, __ms_va_list valist)
978 return MSVCRT_vsnprintf_l(NULL, INT_MAX, format, locale, valist);
981 /*********************************************************************
982 * _vscprintf_p_l (MSVCRT.@)
984 int CDECL MSVCRT__vscprintf_p_l(const char *format,
985 MSVCRT__locale_t locale, __ms_va_list args)
987 printf_arg args_ctx[MSVCRT__ARGMAX+1];
988 struct _str_ctx_a puts_ctx = {INT_MAX, NULL};
989 int ret;
991 memset(args_ctx, 0, sizeof(args_ctx));
993 ret = create_positional_ctx_a(args_ctx, format, args);
994 if(ret < 0) {
995 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
996 *MSVCRT__errno() = MSVCRT_EINVAL;
997 return ret;
998 } else if(ret == 0) {
999 ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale,
1000 MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER,
1001 arg_clbk_valist, NULL, &args);
1002 } else {
1003 ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale,
1004 MSVCRT_PRINTF_POSITIONAL_PARAMS | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER,
1005 arg_clbk_positional, args_ctx, NULL);
1008 return ret;
1011 /*********************************************************************
1012 * _vscprintf_p (MSVCR80.@)
1014 int CDECL MSVCRT__vscprintf_p(const char *format, __ms_va_list argptr)
1016 return MSVCRT__vscprintf_p_l(format, NULL, argptr);
1019 /*********************************************************************
1020 * _snprintf (MSVCRT.@)
1022 int WINAPIV MSVCRT__snprintf(char *str, unsigned int len, const char *format, ...)
1024 int retval;
1025 __ms_va_list valist;
1026 __ms_va_start(valist, format);
1027 retval = MSVCRT_vsnprintf(str, len, format, valist);
1028 __ms_va_end(valist);
1029 return retval;
1032 /*********************************************************************
1033 * _snprintf_l (MSVCRT.@)
1035 int WINAPIV MSVCRT__snprintf_l(char *str, unsigned int count, MSVCRT__locale_t locale,
1036 const char *format, ...)
1038 int retval;
1039 __ms_va_list valist;
1040 __ms_va_start(valist, format);
1041 retval = MSVCRT_vsnprintf_l(str, count, format, locale, valist);
1042 __ms_va_end(valist);
1043 return retval;
1046 /*********************************************************************
1047 * _snprintf_s (MSVCRT.@)
1049 int WINAPIV MSVCRT__snprintf_s(char *str, unsigned int len, unsigned int count,
1050 const char *format, ...)
1052 int retval;
1053 __ms_va_list valist;
1054 __ms_va_start(valist, format);
1055 retval = MSVCRT_vsnprintf_s_l(str, len, count, format, NULL, valist);
1056 __ms_va_end(valist);
1057 return retval;
1060 /*********************************************************************
1061 * _scprintf (MSVCRT.@)
1063 int WINAPIV MSVCRT__scprintf(const char *format, ...)
1065 int retval;
1066 __ms_va_list valist;
1067 __ms_va_start(valist, format);
1068 retval = MSVCRT__vscprintf(format, valist);
1069 __ms_va_end(valist);
1070 return retval;
1073 /*********************************************************************
1074 * _vsnwprintf (MSVCRT.@)
1076 int CDECL MSVCRT_vsnwprintf(MSVCRT_wchar_t *str, MSVCRT_size_t len,
1077 const MSVCRT_wchar_t *format, __ms_va_list valist)
1079 static const MSVCRT_wchar_t nullbyte = '\0';
1080 struct _str_ctx_w ctx = {len, str};
1081 int ret;
1083 ret = pf_printf_w(puts_clbk_str_w, &ctx, format, NULL, 0,
1084 arg_clbk_valist, NULL, &valist);
1085 puts_clbk_str_w(&ctx, 1, &nullbyte);
1086 return ret;
1089 /*********************************************************************
1090 * _vsnwprintf_l (MSVCRT.@)
1092 int CDECL MSVCRT_vsnwprintf_l(MSVCRT_wchar_t *str, MSVCRT_size_t len,
1093 const MSVCRT_wchar_t *format, MSVCRT__locale_t locale,
1094 __ms_va_list valist)
1096 static const MSVCRT_wchar_t nullbyte = '\0';
1097 struct _str_ctx_w ctx = {len, str};
1098 int ret;
1100 ret = pf_printf_w(puts_clbk_str_w, &ctx, format, locale, 0,
1101 arg_clbk_valist, NULL, &valist);
1102 puts_clbk_str_w(&ctx, 1, &nullbyte);
1103 return ret;
1106 static int MSVCRT_vswprintf_p_l_opt(MSVCRT_wchar_t *buffer, MSVCRT_size_t length,
1107 const MSVCRT_wchar_t *format, DWORD options, MSVCRT__locale_t locale, __ms_va_list args)
1109 static const MSVCRT_wchar_t nullbyte = '\0';
1110 printf_arg args_ctx[MSVCRT__ARGMAX+1];
1111 struct _str_ctx_w puts_ctx = {length, buffer};
1112 int ret;
1114 memset(args_ctx, 0, sizeof(args_ctx));
1116 ret = create_positional_ctx_w(args_ctx, format, args);
1117 if(ret < 0) {
1118 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
1119 *MSVCRT__errno() = MSVCRT_EINVAL;
1120 return ret;
1121 } else if(ret == 0)
1122 ret = pf_printf_w(puts_clbk_str_w, &puts_ctx, format, locale, MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
1123 arg_clbk_valist, NULL, &args);
1124 else
1125 ret = pf_printf_w(puts_clbk_str_w, &puts_ctx, format, locale,
1126 MSVCRT_PRINTF_POSITIONAL_PARAMS | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
1127 arg_clbk_positional, args_ctx, NULL);
1129 puts_clbk_str_w(&puts_ctx, 1, &nullbyte);
1130 return ret;
1133 /*********************************************************************
1134 * _vswprintf_p_l (MSVCRT.@)
1136 int CDECL MSVCRT_vswprintf_p_l(MSVCRT_wchar_t *buffer, MSVCRT_size_t length,
1137 const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, __ms_va_list args)
1139 return MSVCRT_vswprintf_p_l_opt(buffer, length, format, 0, locale, args);
1142 #if _MSVCR_VER>=80
1143 /*********************************************************************
1144 * _vswprintf_p (MSVCR80.@)
1146 int CDECL MSVCRT__vswprintf_p(MSVCRT_wchar_t *buffer, MSVCRT_size_t length,
1147 const MSVCRT_wchar_t *format, __ms_va_list args)
1149 return MSVCRT_vswprintf_p_l_opt(buffer, length, format, 0, NULL, args);
1151 #endif
1153 #if _MSVCR_VER>=140
1154 /*********************************************************************
1155 * __stdio_common_vswprintf_p (UCRTBASE.@)
1157 int CDECL MSVCRT__stdio_common_vswprintf_p( unsigned __int64 options,
1158 MSVCRT_wchar_t *str, MSVCRT_size_t count, const MSVCRT_wchar_t *format,
1159 MSVCRT__locale_t locale, __ms_va_list valist )
1161 if (options & ~UCRTBASE_PRINTF_MASK)
1162 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
1163 return MSVCRT_vswprintf_p_l_opt(str, count, format, options & UCRTBASE_PRINTF_MASK, locale, valist);
1165 #endif
1167 /*********************************************************************
1168 * _vsnwprintf_s_l (MSVCRT.@)
1170 int CDECL MSVCRT_vsnwprintf_s_l( MSVCRT_wchar_t *str, MSVCRT_size_t sizeOfBuffer,
1171 MSVCRT_size_t count, const MSVCRT_wchar_t *format,
1172 MSVCRT__locale_t locale, __ms_va_list valist)
1174 return MSVCRT_vsnwprintf_s_l_opt(str, sizeOfBuffer, count, format, 0, locale, valist);
1177 /*********************************************************************
1178 * _vsnwprintf_s (MSVCRT.@)
1180 int CDECL MSVCRT_vsnwprintf_s(MSVCRT_wchar_t *str, MSVCRT_size_t sizeOfBuffer,
1181 MSVCRT_size_t count, const MSVCRT_wchar_t *format, __ms_va_list valist)
1183 return MSVCRT_vsnwprintf_s_l(str, sizeOfBuffer, count,
1184 format, NULL, valist);
1187 /*********************************************************************
1188 * _snwprintf (MSVCRT.@)
1190 int WINAPIV MSVCRT__snwprintf( MSVCRT_wchar_t *str, unsigned int len, const MSVCRT_wchar_t *format, ...)
1192 int retval;
1193 __ms_va_list valist;
1194 __ms_va_start(valist, format);
1195 retval = MSVCRT_vsnwprintf(str, len, format, valist);
1196 __ms_va_end(valist);
1197 return retval;
1200 /*********************************************************************
1201 * _snwprintf_l (MSVCRT.@)
1203 int WINAPIV MSVCRT__snwprintf_l( MSVCRT_wchar_t *str, unsigned int len, const MSVCRT_wchar_t *format,
1204 MSVCRT__locale_t locale, ...)
1206 int retval;
1207 __ms_va_list valist;
1208 __ms_va_start(valist, locale);
1209 retval = MSVCRT_vsnwprintf_l(str, len, format, locale, valist);
1210 __ms_va_end(valist);
1211 return retval;
1214 /*********************************************************************
1215 * _snwprintf_s (MSVCRT.@)
1217 int WINAPIV MSVCRT__snwprintf_s( MSVCRT_wchar_t *str, unsigned int len, unsigned int count,
1218 const MSVCRT_wchar_t *format, ...)
1220 int retval;
1221 __ms_va_list valist;
1222 __ms_va_start(valist, format);
1223 retval = MSVCRT_vsnwprintf_s_l(str, len, count, format, NULL, valist);
1224 __ms_va_end(valist);
1225 return retval;
1228 /*********************************************************************
1229 * _snwprintf_s_l (MSVCRT.@)
1231 int WINAPIV MSVCRT__snwprintf_s_l( MSVCRT_wchar_t *str, unsigned int len, unsigned int count,
1232 const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, ... )
1234 int retval;
1235 __ms_va_list valist;
1236 __ms_va_start(valist, locale);
1237 retval = MSVCRT_vsnwprintf_s_l(str, len, count, format, locale, valist);
1238 __ms_va_end(valist);
1239 return retval;
1242 #if _MSVCR_VER>=140
1244 static int puts_clbk_str_c99_w(void *ctx, int len, const MSVCRT_wchar_t *str)
1246 struct _str_ctx_w *out = ctx;
1248 if(!out->buf)
1249 return len;
1251 if(out->len < len) {
1252 memcpy(out->buf, str, out->len*sizeof(MSVCRT_wchar_t));
1253 out->buf += out->len;
1254 out->len = 0;
1255 return len;
1258 memcpy(out->buf, str, len*sizeof(MSVCRT_wchar_t));
1259 out->buf += len;
1260 out->len -= len;
1261 return len;
1264 /*********************************************************************
1265 * __stdio_common_vswprintf (UCRTBASE.@)
1267 int CDECL MSVCRT__stdio_common_vswprintf( unsigned __int64 options,
1268 MSVCRT_wchar_t *str, MSVCRT_size_t len, const MSVCRT_wchar_t *format,
1269 MSVCRT__locale_t locale, __ms_va_list valist )
1271 static const MSVCRT_wchar_t nullbyte = '\0';
1272 struct _str_ctx_w ctx = {len, str};
1273 int ret;
1275 if (options & ~UCRTBASE_PRINTF_MASK)
1276 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
1277 ret = pf_printf_w(puts_clbk_str_c99_w,
1278 &ctx, format, locale, options & UCRTBASE_PRINTF_MASK, arg_clbk_valist, NULL, &valist);
1279 puts_clbk_str_w(&ctx, 1, &nullbyte);
1281 if(!str)
1282 return ret;
1283 if(options & UCRTBASE_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION)
1284 return ret>len ? -1 : ret;
1285 if(ret>=len) {
1286 if(len) str[len-1] = 0;
1287 return (options & UCRTBASE_PRINTF_STANDARD_SNPRINTF_BEHAVIOUR) ? ret : -2;
1289 return ret;
1292 #endif /* _MSVCR_VER>=140 */
1294 /*********************************************************************
1295 * sprintf (MSVCRT.@)
1297 int WINAPIV MSVCRT_sprintf( char *str, const char *format, ... )
1299 __ms_va_list ap;
1300 int r;
1302 __ms_va_start( ap, format );
1303 r = MSVCRT_vsnprintf( str, INT_MAX, format, ap );
1304 __ms_va_end( ap );
1305 return r;
1308 /*********************************************************************
1309 * sprintf_s (MSVCRT.@)
1311 int WINAPIV MSVCRT_sprintf_s( char *str, MSVCRT_size_t num, const char *format, ... )
1313 __ms_va_list ap;
1314 int r;
1316 __ms_va_start( ap, format );
1317 r = MSVCRT_vsnprintf( str, num, format, ap );
1318 __ms_va_end( ap );
1319 return r;
1322 /*********************************************************************
1323 * _scwprintf (MSVCRT.@)
1325 int WINAPIV MSVCRT__scwprintf( const MSVCRT_wchar_t *format, ... )
1327 __ms_va_list ap;
1328 int r;
1330 __ms_va_start( ap, format );
1331 r = MSVCRT_vsnwprintf( NULL, INT_MAX, format, ap );
1332 __ms_va_end( ap );
1333 return r;
1336 /*********************************************************************
1337 * swprintf (MSVCRT.@)
1339 int WINAPIV MSVCRT_swprintf( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *format, ... )
1341 __ms_va_list ap;
1342 int r;
1344 __ms_va_start( ap, format );
1345 r = MSVCRT_vsnwprintf( str, INT_MAX, format, ap );
1346 __ms_va_end( ap );
1347 return r;
1350 /*********************************************************************
1351 * swprintf_s (MSVCRT.@)
1353 int WINAPIV MSVCRT_swprintf_s(MSVCRT_wchar_t *str, MSVCRT_size_t numberOfElements,
1354 const MSVCRT_wchar_t *format, ... )
1356 __ms_va_list ap;
1357 int r;
1359 __ms_va_start(ap, format);
1360 r = MSVCRT_vsnwprintf_s(str, numberOfElements, INT_MAX, format, ap);
1361 __ms_va_end(ap);
1363 return r;
1366 /*********************************************************************
1367 * _swprintf_s_l (MSVCRT.@)
1369 int WINAPIV MSVCRT__swprintf_s_l(MSVCRT_wchar_t *str, MSVCRT_size_t numberOfElements,
1370 const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, ... )
1372 __ms_va_list ap;
1373 int r;
1375 __ms_va_start(ap, locale);
1376 r = MSVCRT_vsnwprintf_s_l(str, numberOfElements, INT_MAX, format, locale, ap);
1377 __ms_va_end(ap);
1379 return r;
1382 /*********************************************************************
1383 * _vswprintf (MSVCRT.@)
1385 int CDECL MSVCRT_vswprintf( MSVCRT_wchar_t* str, const MSVCRT_wchar_t* format, __ms_va_list args )
1387 return MSVCRT_vsnwprintf( str, INT_MAX, format, args );
1390 /*********************************************************************
1391 * _vswprintf (MSVCRT.@)
1393 int CDECL MSVCRT_vswprintf_l( MSVCRT_wchar_t* str, const MSVCRT_wchar_t* format,
1394 MSVCRT__locale_t locale, __ms_va_list args )
1396 return MSVCRT_vsnwprintf_l( str, INT_MAX, format, locale, args );
1399 /*********************************************************************
1400 * _vscwprintf (MSVCRT.@)
1402 int CDECL MSVCRT__vscwprintf( const MSVCRT_wchar_t *format, __ms_va_list args )
1404 return MSVCRT_vsnwprintf( NULL, INT_MAX, format, args );
1407 /*********************************************************************
1408 * _vscwprintf_l (MSVCRT.@)
1410 int CDECL MSVCRT__vscwprintf_l( const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, __ms_va_list args )
1412 return MSVCRT_vsnwprintf_l( NULL, INT_MAX, format, locale, args );
1415 /*********************************************************************
1416 * _vscwprintf_p_l (MSVCRT.@)
1418 int CDECL MSVCRT__vscwprintf_p_l( const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, __ms_va_list args )
1420 return MSVCRT_vswprintf_p_l_opt( NULL, INT_MAX, format, 0, locale, args );
1423 #if _MSVCR_VER>=80
1424 /*********************************************************************
1425 * _vscwprintf_p (MSVCR80.@)
1427 int CDECL MSVCRT__vscwprintf_p(const MSVCRT_wchar_t *format, __ms_va_list args)
1429 return MSVCRT_vswprintf_p_l_opt(NULL, INT_MAX, format, 0, NULL, args);
1431 #endif
1433 /*********************************************************************
1434 * vswprintf_s (MSVCRT.@)
1436 int CDECL MSVCRT_vswprintf_s(MSVCRT_wchar_t* str, MSVCRT_size_t numberOfElements,
1437 const MSVCRT_wchar_t* format, __ms_va_list args)
1439 return MSVCRT_vsnwprintf_s(str, numberOfElements, INT_MAX, format, args );
1442 /*********************************************************************
1443 * _vswprintf_s_l (MSVCRT.@)
1445 int CDECL MSVCRT_vswprintf_s_l(MSVCRT_wchar_t* str, MSVCRT_size_t numberOfElements,
1446 const MSVCRT_wchar_t* format, MSVCRT__locale_t locale, __ms_va_list args)
1448 return MSVCRT_vsnwprintf_s_l(str, numberOfElements, INT_MAX,
1449 format, locale, args );
1452 static int MSVCRT_vsprintf_p_l_opt(char *buffer, MSVCRT_size_t length, const char *format,
1453 DWORD options, MSVCRT__locale_t locale, __ms_va_list args)
1455 static const char nullbyte = '\0';
1456 printf_arg args_ctx[MSVCRT__ARGMAX+1];
1457 struct _str_ctx_a puts_ctx = {length, buffer};
1458 int ret;
1460 memset(args_ctx, 0, sizeof(args_ctx));
1462 ret = create_positional_ctx_a(args_ctx, format, args);
1463 if(ret < 0) {
1464 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
1465 *MSVCRT__errno() = MSVCRT_EINVAL;
1466 return ret;
1467 } else if(ret == 0)
1468 ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale,
1469 MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options, arg_clbk_valist, NULL, &args);
1470 else
1471 ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale,
1472 MSVCRT_PRINTF_POSITIONAL_PARAMS | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
1473 arg_clbk_positional, args_ctx, NULL);
1475 puts_clbk_str_a(&puts_ctx, 1, &nullbyte);
1476 return ret;
1479 /*********************************************************************
1480 * _vsprintf_p_l (MSVCRT.@)
1482 int CDECL MSVCRT_vsprintf_p_l(char *buffer, MSVCRT_size_t length, const char *format,
1483 MSVCRT__locale_t locale, __ms_va_list args)
1485 return MSVCRT_vsprintf_p_l_opt(buffer, length, format, 0, locale, args);
1488 /*********************************************************************
1489 * _vsprintf_p (MSVCRT.@)
1491 int CDECL MSVCRT_vsprintf_p(char *buffer, MSVCRT_size_t length,
1492 const char *format, __ms_va_list args)
1494 return MSVCRT_vsprintf_p_l(buffer, length, format, NULL, args);
1497 #if _MSVCR_VER>=140
1498 /*********************************************************************
1499 * __stdio_common_vsprintf_p (UCRTBASE.@)
1501 int CDECL MSVCRT__stdio_common_vsprintf_p(unsigned __int64 options, char *buffer, MSVCRT_size_t length,
1502 const char *format, MSVCRT__locale_t locale, __ms_va_list args)
1504 if (options & ~UCRTBASE_PRINTF_MASK)
1505 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
1506 return MSVCRT_vsprintf_p_l_opt(buffer, length, format, options & UCRTBASE_PRINTF_MASK, locale, args);
1508 #endif
1510 /*********************************************************************
1511 * _sprintf_p_l (MSVCRT.@)
1513 int WINAPIV MSVCRT_sprintf_p_l(char *buffer, MSVCRT_size_t length,
1514 const char *format, MSVCRT__locale_t locale, ...)
1516 __ms_va_list valist;
1517 int r;
1519 __ms_va_start(valist, locale);
1520 r = MSVCRT_vsprintf_p_l(buffer, length, format, locale, valist);
1521 __ms_va_end(valist);
1523 return r;
1526 /*********************************************************************
1527 * __swprintf_l (MSVCRT.@)
1529 int WINAPIV MSVCRT___swprintf_l( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *format,
1530 MSVCRT__locale_t locale, ...)
1532 int retval;
1533 __ms_va_list valist;
1534 __ms_va_start(valist, locale);
1535 retval = MSVCRT_vswprintf_l(str, format, locale, valist);
1536 __ms_va_end(valist);
1537 return retval;
1540 #if _MSVCR_VER>=80
1541 /*********************************************************************
1542 * _sprintf_p (MSVCR80.@)
1544 int WINAPIV MSVCRT__sprintf_p(char *buffer, MSVCRT_size_t length, const char *format, ...)
1546 __ms_va_list valist;
1547 int r;
1549 __ms_va_start(valist, format);
1550 r = MSVCRT_vsprintf_p_l(buffer, length, format, NULL, valist);
1551 __ms_va_end(valist);
1553 return r;
1555 #endif
1557 /*********************************************************************
1558 * _swprintf_p_l (MSVCRT.@)
1560 int WINAPIV MSVCRT_swprintf_p_l(MSVCRT_wchar_t *buffer, MSVCRT_size_t length,
1561 const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, ...)
1563 __ms_va_list valist;
1564 int r;
1566 __ms_va_start(valist, locale);
1567 r = MSVCRT_vswprintf_p_l_opt(buffer, length, format, 0, locale, valist);
1568 __ms_va_end(valist);
1570 return r;
1573 /*********************************************************************
1574 * _wcscoll_l (MSVCRT.@)
1576 int CDECL MSVCRT__wcscoll_l(const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2, MSVCRT__locale_t locale)
1578 MSVCRT_pthreadlocinfo locinfo;
1580 if(!locale)
1581 locinfo = get_locinfo();
1582 else
1583 locinfo = locale->locinfo;
1585 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE])
1586 return strcmpW(str1, str2);
1587 return CompareStringW(locinfo->lc_handle[MSVCRT_LC_COLLATE], 0, str1, -1, str2, -1)-CSTR_EQUAL;
1590 /*********************************************************************
1591 * wcscoll (MSVCRT.@)
1593 int CDECL MSVCRT_wcscoll( const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2 )
1595 return MSVCRT__wcscoll_l(str1, str2, NULL);
1598 /*********************************************************************
1599 * wcspbrk (MSVCRT.@)
1601 MSVCRT_wchar_t* CDECL MSVCRT_wcspbrk( const MSVCRT_wchar_t* str, const MSVCRT_wchar_t* accept )
1603 const MSVCRT_wchar_t* p;
1605 while (*str)
1607 for (p = accept; *p; p++) if (*p == *str) return (MSVCRT_wchar_t*)str;
1608 str++;
1610 return NULL;
1613 /*********************************************************************
1614 * wcstok_s (MSVCRT.@)
1616 MSVCRT_wchar_t * CDECL MSVCRT_wcstok_s( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *delim,
1617 MSVCRT_wchar_t **next_token )
1619 MSVCRT_wchar_t *ret;
1621 if (!MSVCRT_CHECK_PMT(delim != NULL)) return NULL;
1622 if (!MSVCRT_CHECK_PMT(next_token != NULL)) return NULL;
1623 if (!MSVCRT_CHECK_PMT(str != NULL || *next_token != NULL)) return NULL;
1625 if (!str) str = *next_token;
1627 while (*str && strchrW( delim, *str )) str++;
1628 if (!*str) return NULL;
1629 ret = str++;
1630 while (*str && !strchrW( delim, *str )) str++;
1631 if (*str) *str++ = 0;
1632 *next_token = str;
1633 return ret;
1636 /*********************************************************************
1637 * wcstok (MSVCRT.@)
1639 #if _MSVCR_VER>=140
1640 MSVCRT_wchar_t * CDECL MSVCRT_wcstok( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *delim, MSVCRT_wchar_t **ctx )
1642 if (!ctx)
1643 ctx = &msvcrt_get_thread_data()->wcstok_next;
1644 return MSVCRT_wcstok_s(str, delim, ctx);
1646 #else
1647 MSVCRT_wchar_t * CDECL MSVCRT_wcstok( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *delim )
1649 return MSVCRT_wcstok_s(str, delim, &msvcrt_get_thread_data()->wcstok_next);
1651 #endif
1653 /*********************************************************************
1654 * _wctomb_s_l (MSVCRT.@)
1656 int CDECL MSVCRT__wctomb_s_l(int *len, char *mbchar, MSVCRT_size_t size,
1657 MSVCRT_wchar_t wch, MSVCRT__locale_t locale)
1659 MSVCRT_pthreadlocinfo locinfo;
1660 BOOL error;
1661 int mblen;
1663 if(!mbchar && size>0) {
1664 if(len)
1665 *len = 0;
1666 return 0;
1669 if(len)
1670 *len = -1;
1672 if(!MSVCRT_CHECK_PMT(size <= INT_MAX))
1673 return MSVCRT_EINVAL;
1675 if(!locale)
1676 locinfo = get_locinfo();
1677 else
1678 locinfo = locale->locinfo;
1680 if(!locinfo->lc_codepage) {
1681 if(wch > 0xff) {
1682 if(mbchar && size>0)
1683 memset(mbchar, 0, size);
1684 *MSVCRT__errno() = MSVCRT_EILSEQ;
1685 return MSVCRT_EILSEQ;
1688 if(!MSVCRT_CHECK_PMT_ERR(size >= 1, MSVCRT_ERANGE))
1689 return MSVCRT_ERANGE;
1691 *mbchar = wch;
1692 if(len)
1693 *len = 1;
1694 return 0;
1697 mblen = WideCharToMultiByte(locinfo->lc_codepage, 0, &wch, 1, mbchar, size, NULL, &error);
1698 if(!mblen || error) {
1699 if(!mblen && GetLastError()==ERROR_INSUFFICIENT_BUFFER) {
1700 if(mbchar && size>0)
1701 memset(mbchar, 0, size);
1703 MSVCRT_INVALID_PMT("insufficient buffer size", MSVCRT_ERANGE);
1704 return MSVCRT_ERANGE;
1707 *MSVCRT__errno() = MSVCRT_EILSEQ;
1708 return MSVCRT_EILSEQ;
1711 if(len)
1712 *len = mblen;
1713 return 0;
1716 /*********************************************************************
1717 * wctomb_s (MSVCRT.@)
1719 int CDECL MSVCRT_wctomb_s(int *len, char *mbchar, MSVCRT_size_t size, MSVCRT_wchar_t wch)
1721 return MSVCRT__wctomb_s_l(len, mbchar, size, wch, NULL);
1724 /*********************************************************************
1725 * _wctomb_l (MSVCRT.@)
1727 int CDECL MSVCRT__wctomb_l(char *dst, MSVCRT_wchar_t ch, MSVCRT__locale_t locale)
1729 int len;
1731 MSVCRT__wctomb_s_l(&len, dst, dst ? MSVCRT_MB_LEN_MAX : 0, ch, locale);
1732 return len;
1735 /*********************************************************************
1736 * wctomb (MSVCRT.@)
1738 INT CDECL MSVCRT_wctomb( char *dst, MSVCRT_wchar_t ch )
1740 return MSVCRT__wctomb_l(dst, ch, NULL);
1743 /*********************************************************************
1744 * wctob (MSVCRT.@)
1746 INT CDECL MSVCRT_wctob( MSVCRT_wint_t wchar )
1748 char out;
1749 BOOL error;
1750 UINT codepage = get_locinfo()->lc_codepage;
1752 if(!codepage) {
1753 if (wchar < 0xff)
1754 return (signed char)wchar;
1755 else
1756 return MSVCRT_EOF;
1757 } else if(WideCharToMultiByte( codepage, 0, &wchar, 1, &out, 1, NULL, &error ) && !error)
1758 return (INT)out;
1759 return MSVCRT_EOF;
1762 /*********************************************************************
1763 * wcrtomb_s (MSVCRT.@)
1765 INT CDECL MSVCRT_wcrtomb_s(MSVCRT_size_t *len, char *mbchar,
1766 MSVCRT_size_t size, MSVCRT_wchar_t wch, MSVCRT_mbstate_t *s)
1768 int ilen, ret;
1770 if (s) *s = 0;
1771 ret = MSVCRT_wctomb_s(&ilen, mbchar, size, wch);
1772 if (len) *len = ilen;
1773 return ret;
1776 /*********************************************************************
1777 * wcrtomb (MSVCRT.@)
1779 MSVCRT_size_t CDECL MSVCRT_wcrtomb( char *dst, MSVCRT_wchar_t ch, MSVCRT_mbstate_t *s)
1781 if(s)
1782 *s = 0;
1783 return MSVCRT_wctomb(dst, ch);
1786 /*********************************************************************
1787 * iswalnum (MSVCRT.@)
1789 INT CDECL MSVCRT_iswalnum( MSVCRT_wchar_t wc )
1791 return isalnumW( wc );
1794 /*********************************************************************
1795 * _iswalnum_l (MSVCRT.@)
1797 int CDECL MSVCRT__iswalnum_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
1799 return isalnumW( wc );
1802 /*********************************************************************
1803 * iswalpha (MSVCRT.@)
1805 INT CDECL MSVCRT_iswalpha( MSVCRT_wchar_t wc )
1807 return isalphaW( wc );
1810 /*********************************************************************
1811 * iswalpha_l (MSVCRT.@)
1813 INT CDECL MSVCRT__iswalpha_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
1815 return isalphaW( wc );
1818 /*********************************************************************
1819 * iswcntrl (MSVCRT.@)
1821 INT CDECL MSVCRT_iswcntrl( MSVCRT_wchar_t wc )
1823 return iscntrlW( wc );
1826 /*********************************************************************
1827 * _iswcntrl_l (MSVCRT.@)
1829 int CDECL MSVCRT__iswcntrl_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
1831 return iscntrlW( wc );
1834 /*********************************************************************
1835 * iswdigit (MSVCRT.@)
1837 INT CDECL MSVCRT_iswdigit( MSVCRT_wchar_t wc )
1839 return isdigitW( wc );
1842 /*********************************************************************
1843 * _iswdigit_l (MSVCRT.@)
1845 INT CDECL MSVCRT__iswdigit_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
1847 return isdigitW( wc );
1850 /*********************************************************************
1851 * iswgraph (MSVCRT.@)
1853 INT CDECL MSVCRT_iswgraph( MSVCRT_wchar_t wc )
1855 return isgraphW( wc );
1858 /*********************************************************************
1859 * _iswgraph_l (MSVCRT.@)
1861 int CDECL MSVCRT__iswgraph_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
1863 return isgraphW( wc );
1866 /*********************************************************************
1867 * iswlower (MSVCRT.@)
1869 INT CDECL MSVCRT_iswlower( MSVCRT_wchar_t wc )
1871 return islowerW( wc );
1874 /*********************************************************************
1875 * _iswlower_l (MSVCRT.@)
1877 int CDECL MSVCRT__iswlower_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
1879 return islowerW( wc );
1882 /*********************************************************************
1883 * iswprint (MSVCRT.@)
1885 INT CDECL MSVCRT_iswprint( MSVCRT_wchar_t wc )
1887 return isprintW( wc );
1890 /*********************************************************************
1891 * _iswprint_l (MSVCRT.@)
1893 int CDECL MSVCRT__iswprint_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
1895 return isprintW( wc );
1898 /*********************************************************************
1899 * _iswpunct_l (MSVCRT.@)
1901 INT CDECL MSVCRT__iswpunct_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
1903 return ispunctW( wc );
1906 /*********************************************************************
1907 * iswpunct (MSVCRT.@)
1909 INT CDECL MSVCRT_iswpunct( MSVCRT_wchar_t wc )
1911 return ispunctW( wc );
1914 /*********************************************************************
1915 * _iswspace_l (MSVCRT.@)
1917 INT CDECL MSVCRT__iswspace_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
1919 return isspaceW( wc );
1922 /*********************************************************************
1923 * iswspace (MSVCRT.@)
1925 INT CDECL MSVCRT_iswspace( MSVCRT_wchar_t wc )
1927 return isspaceW( wc );
1930 /*********************************************************************
1931 * iswupper (MSVCRT.@)
1933 INT CDECL MSVCRT_iswupper( MSVCRT_wchar_t wc )
1935 return isupperW( wc );
1938 /*********************************************************************
1939 * _iswupper_l (MSVCRT.@)
1941 int CDECL MSVCRT__iswupper_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
1943 return isupperW( wc );
1946 /*********************************************************************
1947 * iswxdigit (MSVCRT.@)
1949 INT CDECL MSVCRT_iswxdigit( MSVCRT_wchar_t wc )
1951 return isxdigitW( wc );
1954 /*********************************************************************
1955 * _iswxdigit_l (MSVCRT.@)
1957 int CDECL MSVCRT__iswxdigit_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
1959 return isxdigitW( wc );
1962 /*********************************************************************
1963 * _iswctype_l (MSVCRT.@)
1965 INT CDECL MSVCRT__iswctype_l( MSVCRT_wchar_t wc, MSVCRT_wctype_t type, MSVCRT__locale_t locale )
1967 return (get_char_typeW(wc) & 0xffff) & type;
1970 /*********************************************************************
1971 * iswctype (MSVCRT.@)
1973 INT CDECL MSVCRT_iswctype( MSVCRT_wchar_t wc, MSVCRT_wctype_t type )
1975 return (get_char_typeW(wc) & 0xfff) & type;
1978 /*********************************************************************
1979 * _iswblank_l (MSVCRT.@)
1981 INT CDECL MSVCRT__iswblank_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
1983 return wc == '\t' || MSVCRT__iswctype_l( wc, MSVCRT__BLANK, locale );
1986 /*********************************************************************
1987 * iswblank (MSVCRT.@)
1989 INT CDECL MSVCRT_iswblank( MSVCRT_wchar_t wc )
1991 return wc == '\t' || MSVCRT__iswctype_l( wc, MSVCRT__BLANK, NULL );
1994 /*********************************************************************
1995 * wcscpy_s (MSVCRT.@)
1997 INT CDECL MSVCRT_wcscpy_s( MSVCRT_wchar_t* wcDest, MSVCRT_size_t numElement, const MSVCRT_wchar_t *wcSrc)
1999 MSVCRT_size_t size = 0;
2001 if(!MSVCRT_CHECK_PMT(wcDest)) return MSVCRT_EINVAL;
2002 if(!MSVCRT_CHECK_PMT(numElement)) return MSVCRT_EINVAL;
2004 if(!MSVCRT_CHECK_PMT(wcSrc))
2006 wcDest[0] = 0;
2007 return MSVCRT_EINVAL;
2010 size = strlenW(wcSrc) + 1;
2012 if(!MSVCRT_CHECK_PMT_ERR(size <= numElement, MSVCRT_ERANGE))
2014 wcDest[0] = 0;
2015 return MSVCRT_ERANGE;
2018 memmove( wcDest, wcSrc, size*sizeof(WCHAR) );
2020 return 0;
2023 /******************************************************************
2024 * wcsncpy (MSVCRT.@)
2026 MSVCRT_wchar_t* __cdecl MSVCRT_wcsncpy( MSVCRT_wchar_t* s1,
2027 const MSVCRT_wchar_t *s2, MSVCRT_size_t n )
2029 MSVCRT_size_t i;
2031 for(i=0; i<n; i++)
2032 if(!(s1[i] = s2[i])) break;
2033 for(; i<n; i++)
2034 s1[i] = 0;
2035 return s1;
2038 /******************************************************************
2039 * wcsncpy_s (MSVCRT.@)
2041 INT CDECL MSVCRT_wcsncpy_s( MSVCRT_wchar_t* wcDest, MSVCRT_size_t numElement, const MSVCRT_wchar_t *wcSrc,
2042 MSVCRT_size_t count )
2044 WCHAR *p = wcDest;
2045 BOOL truncate = (count == MSVCRT__TRUNCATE);
2047 if(!wcDest && !numElement && !count)
2048 return 0;
2050 if (!wcDest || !numElement)
2051 return MSVCRT_EINVAL;
2053 if (!wcSrc)
2055 *wcDest = 0;
2056 return count ? MSVCRT_EINVAL : 0;
2059 while (numElement && count && *wcSrc)
2061 *p++ = *wcSrc++;
2062 numElement--;
2063 count--;
2065 if (!numElement && truncate)
2067 *(p-1) = 0;
2068 return MSVCRT_STRUNCATE;
2070 else if (!numElement)
2072 *wcDest = 0;
2073 return MSVCRT_ERANGE;
2076 *p = 0;
2077 return 0;
2080 /******************************************************************
2081 * wcscat_s (MSVCRT.@)
2084 INT CDECL MSVCRT_wcscat_s(MSVCRT_wchar_t* dst, MSVCRT_size_t elem, const MSVCRT_wchar_t* src)
2086 MSVCRT_wchar_t* ptr = dst;
2088 if (!dst || elem == 0) return MSVCRT_EINVAL;
2089 if (!src)
2091 dst[0] = '\0';
2092 return MSVCRT_EINVAL;
2095 /* seek to end of dst string (or elem if no end of string is found */
2096 while (ptr < dst + elem && *ptr != '\0') ptr++;
2097 while (ptr < dst + elem)
2099 if ((*ptr++ = *src++) == '\0') return 0;
2101 /* not enough space */
2102 dst[0] = '\0';
2103 return MSVCRT_ERANGE;
2106 /*********************************************************************
2107 * wcsncat_s (MSVCRT.@)
2110 INT CDECL MSVCRT_wcsncat_s(MSVCRT_wchar_t *dst, MSVCRT_size_t elem,
2111 const MSVCRT_wchar_t *src, MSVCRT_size_t count)
2113 MSVCRT_size_t srclen;
2114 MSVCRT_wchar_t dststart;
2115 INT ret = 0;
2117 if (!MSVCRT_CHECK_PMT(dst != NULL)) return MSVCRT_EINVAL;
2118 if (!MSVCRT_CHECK_PMT(elem > 0)) return MSVCRT_EINVAL;
2119 if (!MSVCRT_CHECK_PMT(src != NULL || count == 0)) return MSVCRT_EINVAL;
2121 if (count == 0)
2122 return 0;
2124 for (dststart = 0; dststart < elem; dststart++)
2126 if (dst[dststart] == '\0')
2127 break;
2129 if (dststart == elem)
2131 MSVCRT_INVALID_PMT("dst[elem] is not NULL terminated\n", MSVCRT_EINVAL);
2132 return MSVCRT_EINVAL;
2135 if (count == MSVCRT__TRUNCATE)
2137 srclen = strlenW(src);
2138 if (srclen >= (elem - dststart))
2140 srclen = elem - dststart - 1;
2141 ret = MSVCRT_STRUNCATE;
2144 else
2145 srclen = min(strlenW(src), count);
2146 if (srclen < (elem - dststart))
2148 memcpy(&dst[dststart], src, srclen*sizeof(MSVCRT_wchar_t));
2149 dst[dststart+srclen] = '\0';
2150 return ret;
2152 MSVCRT_INVALID_PMT("dst[elem] is too small", MSVCRT_ERANGE);
2153 dst[0] = '\0';
2154 return MSVCRT_ERANGE;
2157 /*********************************************************************
2158 * wctoint (INTERNAL)
2160 static int wctoint(WCHAR c, int base)
2162 int v = -1;
2163 if ('0' <= c && c <= '9')
2164 v = c - '0';
2165 else if ('A' <= c && c <= 'Z')
2166 v = c - 'A' + 10;
2167 else if ('a' <= c && c <= 'z')
2168 v = c - 'a' + 10;
2169 else {
2170 /* NOTE: wine_fold_string(MAP_FOLDDIGITS) supports too many things. */
2171 /* Unicode points that contain digits 0-9; keep this sorted! */
2172 static const WCHAR zeros[] = {
2173 0x660, 0x6f0, 0x966, 0x9e6, 0xa66, 0xae6, 0xb66, 0xc66, 0xce6,
2174 0xd66, 0xe50, 0xed0, 0xf20, 0x1040, 0x17e0, 0x1810, 0xff10
2176 int i;
2177 for (i = 0; i < ARRAY_SIZE(zeros) && c >= zeros[i]; ++i) {
2178 if (zeros[i] <= c && c <= zeros[i] + 9) {
2179 v = c - zeros[i];
2180 break;
2184 return v < base ? v : -1;
2187 /*********************************************************************
2188 * _wcstoi64_l (MSVCRT.@)
2190 * FIXME: locale parameter is ignored
2192 __int64 CDECL MSVCRT__wcstoi64_l(const MSVCRT_wchar_t *nptr,
2193 MSVCRT_wchar_t **endptr, int base, MSVCRT__locale_t locale)
2195 BOOL negative = FALSE, empty = TRUE;
2196 __int64 ret = 0;
2198 TRACE("(%s %p %d %p)\n", debugstr_w(nptr), endptr, base, locale);
2200 if (!MSVCRT_CHECK_PMT(nptr != NULL)) return 0;
2201 if (!MSVCRT_CHECK_PMT(base == 0 || base >= 2)) return 0;
2202 if (!MSVCRT_CHECK_PMT(base <= 36)) return 0;
2204 if(endptr)
2205 *endptr = (MSVCRT_wchar_t*)nptr;
2207 while(isspaceW(*nptr)) nptr++;
2209 if(*nptr == '-') {
2210 negative = TRUE;
2211 nptr++;
2212 } else if(*nptr == '+')
2213 nptr++;
2215 if((base==0 || base==16) && wctoint(*nptr, 1)==0 && tolowerW(*(nptr+1))=='x') {
2216 base = 16;
2217 nptr += 2;
2220 if(base == 0) {
2221 if(wctoint(*nptr, 1)==0)
2222 base = 8;
2223 else
2224 base = 10;
2227 while(*nptr) {
2228 int v = wctoint(*nptr, base);
2229 if(v<0)
2230 break;
2232 if(negative)
2233 v = -v;
2235 nptr++;
2236 empty = FALSE;
2238 if(!negative && (ret>MSVCRT_I64_MAX/base || ret*base>MSVCRT_I64_MAX-v)) {
2239 ret = MSVCRT_I64_MAX;
2240 *MSVCRT__errno() = MSVCRT_ERANGE;
2241 } else if(negative && (ret<MSVCRT_I64_MIN/base || ret*base<MSVCRT_I64_MIN-v)) {
2242 ret = MSVCRT_I64_MIN;
2243 *MSVCRT__errno() = MSVCRT_ERANGE;
2244 } else
2245 ret = ret*base + v;
2248 if(endptr && !empty)
2249 *endptr = (MSVCRT_wchar_t*)nptr;
2251 return ret;
2254 /*********************************************************************
2255 * _wcstoi64 (MSVCRT.@)
2257 __int64 CDECL MSVCRT__wcstoi64(const MSVCRT_wchar_t *nptr,
2258 MSVCRT_wchar_t **endptr, int base)
2260 return MSVCRT__wcstoi64_l(nptr, endptr, base, NULL);
2263 /*********************************************************************
2264 * _wcstol_l (MSVCRT.@)
2266 MSVCRT_long CDECL MSVCRT__wcstol_l(const MSVCRT_wchar_t *s,
2267 MSVCRT_wchar_t **end, int base, MSVCRT__locale_t locale)
2269 __int64 ret = MSVCRT__wcstoi64_l(s, end, base, locale);
2271 if(ret > MSVCRT_LONG_MAX) {
2272 ret = MSVCRT_LONG_MAX;
2273 *MSVCRT__errno() = MSVCRT_ERANGE;
2274 }else if(ret < MSVCRT_LONG_MIN) {
2275 ret = MSVCRT_LONG_MIN;
2276 *MSVCRT__errno() = MSVCRT_ERANGE;
2278 return ret;
2281 /*********************************************************************
2282 * wcstol (MSVCRT.@)
2284 MSVCRT_long CDECL MSVCRT_wcstol(const MSVCRT_wchar_t *s,
2285 MSVCRT_wchar_t **end, int base)
2287 return MSVCRT__wcstol_l(s, end, base, NULL);
2290 /*********************************************************************
2291 * _wtoi_l (MSVCRT.@)
2293 int __cdecl MSVCRT__wtoi_l(const MSVCRT_wchar_t *str, MSVCRT__locale_t locale)
2295 __int64 ret = MSVCRT__wcstoi64_l(str, NULL, 10, locale);
2297 if(ret > INT_MAX) {
2298 ret = INT_MAX;
2299 *MSVCRT__errno() = MSVCRT_ERANGE;
2300 } else if(ret < INT_MIN) {
2301 ret = INT_MIN;
2302 *MSVCRT__errno() = MSVCRT_ERANGE;
2304 return ret;
2307 /*********************************************************************
2308 * _wtoi (MSVCRT.@)
2310 int __cdecl MSVCRT__wtoi(const MSVCRT_wchar_t *str)
2312 return MSVCRT__wtoi_l(str, NULL);
2315 /*********************************************************************
2316 * _wtol_l (MSVCRT.@)
2318 MSVCRT_long __cdecl MSVCRT__wtol_l(const MSVCRT_wchar_t *str, MSVCRT__locale_t locale)
2320 __int64 ret = MSVCRT__wcstoi64_l(str, NULL, 10, locale);
2322 if(ret > MSVCRT_LONG_MAX) {
2323 ret = MSVCRT_LONG_MAX;
2324 *MSVCRT__errno() = MSVCRT_ERANGE;
2325 } else if(ret < MSVCRT_LONG_MIN) {
2326 ret = MSVCRT_LONG_MIN;
2327 *MSVCRT__errno() = MSVCRT_ERANGE;
2329 return ret;
2332 /*********************************************************************
2333 * _wtol (MSVCRT.@)
2335 MSVCRT_long __cdecl MSVCRT__wtol(const MSVCRT_wchar_t *str)
2337 return MSVCRT__wtol_l(str, NULL);
2340 #if _MSVCR_VER>=120
2342 /*********************************************************************
2343 * _wtoll_l (MSVCR120.@)
2345 MSVCRT_longlong __cdecl MSVCRT__wtoll_l(const MSVCRT_wchar_t *str, MSVCRT__locale_t locale)
2347 return MSVCRT__wcstoi64_l(str, NULL, 10, locale);
2350 /*********************************************************************
2351 * _wtoll (MSVCR120.@)
2353 MSVCRT_longlong __cdecl MSVCRT__wtoll(const MSVCRT_wchar_t *str)
2355 return MSVCRT__wtoll_l(str, NULL);
2358 #endif /* _MSVCR_VER>=120 */
2360 /*********************************************************************
2361 * _wcstoui64_l (MSVCRT.@)
2363 * FIXME: locale parameter is ignored
2365 unsigned __int64 CDECL MSVCRT__wcstoui64_l(const MSVCRT_wchar_t *nptr,
2366 MSVCRT_wchar_t **endptr, int base, MSVCRT__locale_t locale)
2368 BOOL negative = FALSE, empty = TRUE;
2369 unsigned __int64 ret = 0;
2371 TRACE("(%s %p %d %p)\n", debugstr_w(nptr), endptr, base, locale);
2373 if (!MSVCRT_CHECK_PMT(nptr != NULL)) return 0;
2374 if (!MSVCRT_CHECK_PMT(base == 0 || base >= 2)) return 0;
2375 if (!MSVCRT_CHECK_PMT(base <= 36)) return 0;
2377 if(endptr)
2378 *endptr = (MSVCRT_wchar_t*)nptr;
2380 while(isspaceW(*nptr)) nptr++;
2382 if(*nptr == '-') {
2383 negative = TRUE;
2384 nptr++;
2385 } else if(*nptr == '+')
2386 nptr++;
2388 if((base==0 || base==16) && wctoint(*nptr, 1)==0 && tolowerW(*(nptr+1))=='x') {
2389 base = 16;
2390 nptr += 2;
2393 if(base == 0) {
2394 if(wctoint(*nptr, 1)==0)
2395 base = 8;
2396 else
2397 base = 10;
2400 while(*nptr) {
2401 int v = wctoint(*nptr, base);
2402 if(v<0)
2403 break;
2405 nptr++;
2406 empty = FALSE;
2408 if(ret>MSVCRT_UI64_MAX/base || ret*base>MSVCRT_UI64_MAX-v) {
2409 ret = MSVCRT_UI64_MAX;
2410 *MSVCRT__errno() = MSVCRT_ERANGE;
2411 } else
2412 ret = ret*base + v;
2415 if(endptr && !empty)
2416 *endptr = (MSVCRT_wchar_t*)nptr;
2418 return negative ? -ret : ret;
2421 /*********************************************************************
2422 * _wcstoui64 (MSVCRT.@)
2424 unsigned __int64 CDECL MSVCRT__wcstoui64(const MSVCRT_wchar_t *nptr,
2425 MSVCRT_wchar_t **endptr, int base)
2427 return MSVCRT__wcstoui64_l(nptr, endptr, base, NULL);
2430 /*********************************************************************
2431 * _wcstoul_l (MSVCRT.@)
2433 MSVCRT_ulong __cdecl MSVCRT__wcstoul_l(const MSVCRT_wchar_t *s,
2434 MSVCRT_wchar_t **end, int base, MSVCRT__locale_t locale)
2436 __int64 ret = MSVCRT__wcstoi64_l(s, end, base, locale);
2438 if(ret > MSVCRT_ULONG_MAX) {
2439 ret = MSVCRT_ULONG_MAX;
2440 *MSVCRT__errno() = MSVCRT_ERANGE;
2441 }else if(ret < -(__int64)MSVCRT_ULONG_MAX) {
2442 ret = 1;
2443 *MSVCRT__errno() = MSVCRT_ERANGE;
2445 return ret;
2448 /*********************************************************************
2449 * wcstoul (MSVCRT.@)
2451 MSVCRT_ulong __cdecl MSVCRT_wcstoul(const MSVCRT_wchar_t *s, MSVCRT_wchar_t **end, int base)
2453 return MSVCRT__wcstoul_l(s, end, base, NULL);
2456 /******************************************************************
2457 * wcsnlen (MSVCRT.@)
2459 MSVCRT_size_t CDECL MSVCRT_wcsnlen(const MSVCRT_wchar_t *s, MSVCRT_size_t maxlen)
2461 MSVCRT_size_t i;
2463 for (i = 0; i < maxlen; i++)
2464 if (!s[i]) break;
2465 return i;
2468 /*********************************************************************
2469 * _towupper_l (MSVCRT.@)
2471 int CDECL MSVCRT__towupper_l(MSVCRT_wint_t c, MSVCRT__locale_t locale)
2473 MSVCRT_pthreadlocinfo locinfo;
2475 if(!locale)
2476 locinfo = get_locinfo();
2477 else
2478 locinfo = locale->locinfo;
2480 if(!locinfo->lc_handle[MSVCRT_LC_CTYPE]) {
2481 if(c >= 'a' && c <= 'z')
2482 return c + 'A' - 'a';
2483 return c;
2486 return toupperW(c);
2489 /*********************************************************************
2490 * towupper (MSVCRT.@)
2492 int CDECL MSVCRT_towupper(MSVCRT_wint_t c)
2494 return MSVCRT__towupper_l(c, NULL);
2497 /*********************************************************************
2498 * _towlower_l (MSVCRT.@)
2500 int CDECL MSVCRT__towlower_l(MSVCRT_wint_t c, MSVCRT__locale_t locale)
2502 MSVCRT_pthreadlocinfo locinfo;
2504 if(!locale)
2505 locinfo = get_locinfo();
2506 else
2507 locinfo = locale->locinfo;
2509 if(!locinfo->lc_handle[MSVCRT_LC_CTYPE]) {
2510 if(c >= 'A' && c <= 'Z')
2511 return c + 'a' - 'A';
2512 return c;
2515 return tolowerW(c);
2518 /*********************************************************************
2519 * towlower (MSVCRT.@)
2521 int CDECL MSVCRT_towlower(MSVCRT_wint_t c)
2523 return MSVCRT__towlower_l(c, NULL);
2526 /*********************************************************************
2527 * wcschr (MSVCRT.@)
2529 MSVCRT_wchar_t* CDECL MSVCRT_wcschr(const MSVCRT_wchar_t *str, MSVCRT_wchar_t ch)
2531 return strchrW(str, ch);
2534 /*********************************************************************
2535 * wcsrchr (MSVCRT.@)
2537 MSVCRT_wchar_t* CDECL MSVCRT_wcsrchr(const MSVCRT_wchar_t *str, MSVCRT_wchar_t ch)
2539 return strrchrW(str, ch);
2542 /***********************************************************************
2543 * wcslen (MSVCRT.@)
2545 int CDECL MSVCRT_wcslen(const MSVCRT_wchar_t *str)
2547 return strlenW(str);
2550 /*********************************************************************
2551 * wcsstr (MSVCRT.@)
2553 MSVCRT_wchar_t* CDECL MSVCRT_wcsstr(const MSVCRT_wchar_t *str, const MSVCRT_wchar_t *sub)
2555 return strstrW(str, sub);
2558 /*********************************************************************
2559 * _wtoi64_l (MSVCRT.@)
2561 __int64 CDECL MSVCRT__wtoi64_l(const MSVCRT_wchar_t *str, MSVCRT__locale_t locale)
2563 ULONGLONG RunningTotal = 0;
2564 BOOL bMinus = FALSE;
2566 while (isspaceW(*str)) {
2567 str++;
2568 } /* while */
2570 if (*str == '+') {
2571 str++;
2572 } else if (*str == '-') {
2573 bMinus = TRUE;
2574 str++;
2575 } /* if */
2577 while (*str >= '0' && *str <= '9') {
2578 RunningTotal = RunningTotal * 10 + *str - '0';
2579 str++;
2580 } /* while */
2582 return bMinus ? -RunningTotal : RunningTotal;
2585 /*********************************************************************
2586 * _wtoi64 (MSVCRT.@)
2588 __int64 CDECL MSVCRT__wtoi64(const MSVCRT_wchar_t *str)
2590 return MSVCRT__wtoi64_l(str, NULL);
2593 /*********************************************************************
2594 * wcsncmp (MSVCRT.@)
2596 int CDECL MSVCRT_wcsncmp(const MSVCRT_wchar_t *str1, const MSVCRT_wchar_t *str2, int n)
2598 return strncmpW(str1, str2, n);
2601 /*********************************************************************
2602 * _wcsxfrm_l (MSVCRT.@)
2604 MSVCRT_size_t CDECL MSVCRT__wcsxfrm_l(MSVCRT_wchar_t *dest, const MSVCRT_wchar_t *src,
2605 MSVCRT_size_t len, MSVCRT__locale_t locale)
2607 MSVCRT_pthreadlocinfo locinfo;
2608 int i, ret;
2610 if(!MSVCRT_CHECK_PMT(src)) return INT_MAX;
2611 if(!MSVCRT_CHECK_PMT(dest || !len)) return INT_MAX;
2613 if(len > INT_MAX) {
2614 FIXME("len > INT_MAX not supported\n");
2615 len = INT_MAX;
2618 if(!locale)
2619 locinfo = get_locinfo();
2620 else
2621 locinfo = locale->locinfo;
2623 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE]) {
2624 MSVCRT_wcsncpy(dest, src, len);
2625 return strlenW(src);
2628 ret = LCMapStringW(locinfo->lc_handle[MSVCRT_LC_COLLATE],
2629 LCMAP_SORTKEY, src, -1, NULL, 0);
2630 if(!ret) {
2631 if(len) dest[0] = 0;
2632 *MSVCRT__errno() = MSVCRT_EILSEQ;
2633 return INT_MAX;
2635 if(!len) return ret-1;
2637 if(ret > len) {
2638 dest[0] = 0;
2639 *MSVCRT__errno() = MSVCRT_ERANGE;
2640 return ret-1;
2643 ret = LCMapStringW(locinfo->lc_handle[MSVCRT_LC_COLLATE],
2644 LCMAP_SORTKEY, src, -1, dest, len) - 1;
2645 for(i=ret; i>=0; i--)
2646 dest[i] = ((unsigned char*)dest)[i];
2647 return ret;
2650 /*********************************************************************
2651 * wcsxfrm (MSVCRT.@)
2653 MSVCRT_size_t CDECL MSVCRT_wcsxfrm(MSVCRT_wchar_t *dest,
2654 const MSVCRT_wchar_t *src, MSVCRT_size_t len)
2656 return MSVCRT__wcsxfrm_l(dest, src, len, NULL);
2659 /*********************************************************************
2660 * wcscmp (MSVCRT.@)
2662 int CDECL MSVCRT_wcscmp(const MSVCRT_wchar_t *str1, const MSVCRT_wchar_t *str2)
2664 return strcmpW(str1, str2);