mfreadwrite/reader: Add missing allocation check (Coverity).
[wine/zf.git] / dlls / msvcrt / wcs.c
blob343dec704778fb0250389039838d7480a26d72a3
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
22 #define _NO_CRT_STDIO_INLINE
23 #include <limits.h>
24 #include <locale.h>
25 #include <math.h>
26 #include <assert.h>
27 #include <wchar.h>
28 #include <wctype.h>
29 #include "msvcrt.h"
30 #include "winnls.h"
31 #include "wtypes.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
36 typedef struct
38 enum { LEN_DEFAULT, LEN_SHORT, LEN_LONG } IntegerLength;
39 BOOLEAN IntegerDouble, IntegerNative, LeftAlign, Alternate, PadZero;
40 BOOLEAN WideString, NaturalString;
41 int FieldLength, Precision;
42 char Sign, Format;
43 } pf_flags;
45 static BOOL n_format_enabled = TRUE;
47 #include "printf.h"
48 #define PRINTF_WIDE
49 #include "printf.h"
50 #undef PRINTF_WIDE
52 #if _MSVCR_VER>=80
54 /*********************************************************************
55 * _get_printf_count_output (MSVCR80.@)
57 int CDECL _get_printf_count_output( void )
59 return n_format_enabled ? 1 : 0;
62 /*********************************************************************
63 * _set_printf_count_output (MSVCR80.@)
65 int CDECL _set_printf_count_output( int enable )
67 BOOL old = n_format_enabled;
68 n_format_enabled = enable != 0;
69 return old ? 1 : 0;
72 #endif /* _MSVCR_VER>=80 */
74 /*********************************************************************
75 * _wcsdup (MSVCRT.@)
77 wchar_t* CDECL _wcsdup( const wchar_t* str )
79 wchar_t* ret = NULL;
80 if (str)
82 int size = (wcslen(str) + 1) * sizeof(wchar_t);
83 ret = malloc( size );
84 if (ret) memcpy( ret, str, size );
86 return ret;
89 /*********************************************************************
90 * _towlower_l (MSVCRT.@)
92 wint_t CDECL _towlower_l(wint_t c, _locale_t locale)
94 pthreadlocinfo locinfo;
95 wchar_t ret;
97 if(!locale)
98 locinfo = get_locinfo();
99 else
100 locinfo = locale->locinfo;
102 if(!locinfo->lc_handle[LC_CTYPE]) {
103 if(c >= 'A' && c <= 'Z')
104 return c + 'a' - 'A';
105 return c;
108 if(!LCMapStringW(locinfo->lc_handle[LC_CTYPE], LCMAP_LOWERCASE, &c, 1, &ret, 1))
109 return c;
110 return ret;
113 /*********************************************************************
114 * towlower (MSVCRT.@)
116 wint_t CDECL towlower(wint_t c)
118 return _towlower_l(c, NULL);
121 INT CDECL _wcsicmp_l(const wchar_t *str1, const wchar_t *str2, _locale_t locale)
123 _locale_tstruct tmp = {0};
124 wchar_t c1, c2;
126 if(!MSVCRT_CHECK_PMT(str1 != NULL) || !MSVCRT_CHECK_PMT(str2 != NULL))
127 return _NLSCMPERROR;
129 if(!locale)
130 locale = get_current_locale_noalloc(&tmp);
134 c1 = _towlower_l(*str1++, locale);
135 c2 = _towlower_l(*str2++, locale);
136 } while(c1 && (c1 == c2));
138 free_locale_noalloc(&tmp);
139 return c1 - c2;
142 /*********************************************************************
143 * towctrans (MSVCR120.@)
145 wint_t CDECL towctrans(wint_t c, wctrans_t category)
147 if(category == 1)
148 return _towupper_l(c, NULL);
149 return _towlower_l(c, NULL);
152 /*********************************************************************
153 * _wcsicmp (MSVCRT.@)
155 INT CDECL _wcsicmp( const wchar_t* str1, const wchar_t* str2 )
157 return _wcsicmp_l(str1, str2, NULL);
160 /*********************************************************************
161 * _wcsnicmp_l (MSVCRT.@)
163 INT CDECL _wcsnicmp_l(const wchar_t *str1, const wchar_t *str2,
164 size_t n, _locale_t locale)
166 _locale_tstruct tmp = {0};
167 wchar_t c1, c2;
169 if (!n)
170 return 0;
172 if(!MSVCRT_CHECK_PMT(str1 != NULL) || !MSVCRT_CHECK_PMT(str2 != NULL))
173 return _NLSCMPERROR;
175 if(!locale)
176 locale = get_current_locale_noalloc(&tmp);
180 c1 = _towlower_l(*str1++, locale);
181 c2 = _towlower_l(*str2++, locale);
182 } while(--n && c1 && (c1 == c2));
184 free_locale_noalloc(&tmp);
185 return c1 - c2;
188 /*********************************************************************
189 * _wcsnicmp (MSVCRT.@)
191 INT CDECL _wcsnicmp(const wchar_t *str1, const wchar_t *str2, size_t n)
193 return _wcsnicmp_l(str1, str2, n, NULL);
196 /*********************************************************************
197 * _wcsicoll_l (MSVCRT.@)
199 int CDECL _wcsicoll_l(const wchar_t* str1, const wchar_t* str2, _locale_t locale)
201 pthreadlocinfo locinfo;
203 if(!locale)
204 locinfo = get_locinfo();
205 else
206 locinfo = locale->locinfo;
208 if(!locinfo->lc_handle[LC_COLLATE])
210 wchar_t c1, c2;
214 c1 = *str1++;
215 if (c1 >= 'A' && c1 <= 'Z')
216 c1 += 'a' - 'A';
218 c2 = *str2++;
219 if (c2 >= 'A' && c2 <= 'Z')
220 c2 += 'a' - 'A';
221 } while(c1 && (c1 == c2));
222 return c1 - c2;
225 return CompareStringW(locinfo->lc_handle[LC_COLLATE], NORM_IGNORECASE,
226 str1, -1, str2, -1)-CSTR_EQUAL;
229 /*********************************************************************
230 * _wcsicoll (MSVCRT.@)
232 INT CDECL _wcsicoll( const wchar_t* str1, const wchar_t* str2 )
234 return _wcsicoll_l(str1, str2, NULL);
237 /*********************************************************************
238 * _wcsnicoll_l (MSVCRT.@)
240 int CDECL _wcsnicoll_l(const wchar_t* str1, const wchar_t* str2,
241 size_t count, _locale_t locale)
243 pthreadlocinfo locinfo;
245 if(!locale)
246 locinfo = get_locinfo();
247 else
248 locinfo = locale->locinfo;
250 if(!locinfo->lc_handle[LC_COLLATE])
252 wchar_t c1, c2;
254 if (!count)
255 return 0;
259 c1 = *str1++;
260 if (c1 >= 'A' && c1 <= 'Z')
261 c1 += 'a' - 'A';
263 c2 = *str2++;
264 if (c2 >= 'A' && c2 <= 'Z')
265 c2 += 'a' - 'A';
266 } while(--count && c1 && (c1 == c2));
267 return c1 - c2;
270 return CompareStringW(locinfo->lc_handle[LC_COLLATE], NORM_IGNORECASE,
271 str1, wcsnlen(str1, count),
272 str2, wcsnlen(str2, count))-CSTR_EQUAL;
275 /*********************************************************************
276 * _wcsnicoll (MSVCRT.@)
278 INT CDECL _wcsnicoll( const wchar_t* str1, const wchar_t* str2, size_t count )
280 return _wcsnicoll_l(str1, str2, count, NULL);
283 /*********************************************************************
284 * _wcsnset (MSVCRT.@)
286 wchar_t* CDECL _wcsnset( wchar_t* str, wchar_t c, size_t n )
288 wchar_t* ret = str;
289 while ((n-- > 0) && *str) *str++ = c;
290 return ret;
293 /*********************************************************************
294 * _wcsnset_s (MSVCRT.@)
296 int CDECL _wcsnset_s( wchar_t *str, size_t size, wchar_t c, size_t count )
298 size_t i;
300 if(!str && !size && !count) return 0;
301 if(!MSVCRT_CHECK_PMT(str != NULL)) return EINVAL;
302 if(!MSVCRT_CHECK_PMT(size > 0)) return EINVAL;
304 for(i=0; i<size-1 && i<count; i++) {
305 if(!str[i]) return 0;
306 str[i] = c;
308 for(; i<size; i++)
309 if(!str[i]) return 0;
311 str[0] = 0;
312 _invalid_parameter(NULL, NULL, NULL, 0, 0);
313 *_errno() = EINVAL;
314 return EINVAL;
317 /*********************************************************************
318 * _wcsrev (MSVCRT.@)
320 wchar_t* CDECL _wcsrev( wchar_t* str )
322 wchar_t* ret = str;
323 wchar_t* end = str + wcslen(str) - 1;
324 while (end > str)
326 wchar_t t = *end;
327 *end-- = *str;
328 *str++ = t;
330 return ret;
333 /*********************************************************************
334 * _wcsset_s (MSVCRT.@)
336 int CDECL _wcsset_s( wchar_t *str, size_t n, wchar_t c )
338 wchar_t *p = str;
340 if(!MSVCRT_CHECK_PMT(str != NULL)) return EINVAL;
341 if(!MSVCRT_CHECK_PMT(n)) return EINVAL;
343 while(*p && --n) *p++ = c;
344 if(!n) {
345 str[0] = 0;
346 _invalid_parameter(NULL, NULL, NULL, 0, 0);
347 *_errno() = EINVAL;
348 return EINVAL;
350 return 0;
353 /*********************************************************************
354 * _wcsset (MSVCRT.@)
356 wchar_t* CDECL _wcsset( wchar_t* str, wchar_t c )
358 wchar_t* ret = str;
359 while (*str) *str++ = c;
360 return ret;
363 /******************************************************************
364 * _wcsupr_s_l (MSVCRT.@)
366 int CDECL _wcsupr_s_l( wchar_t* str, size_t n, _locale_t locale )
368 _locale_tstruct tmp = {0};
369 wchar_t* ptr = str;
371 if (!str || !n)
373 if (str) *str = '\0';
374 *_errno() = EINVAL;
375 return EINVAL;
378 if(!locale)
379 locale = get_current_locale_noalloc(&tmp);
381 while (n--)
383 if (!*ptr)
385 free_locale_noalloc(&tmp);
386 return 0;
388 *ptr = _towupper_l(*ptr, locale);
389 ptr++;
392 free_locale_noalloc(&tmp);
394 /* MSDN claims that the function should return and set errno to
395 * ERANGE, which doesn't seem to be true based on the tests. */
396 *str = '\0';
397 *_errno() = EINVAL;
398 return EINVAL;
401 /******************************************************************
402 * _wcsupr_s (MSVCRT.@)
405 INT CDECL _wcsupr_s( wchar_t* str, size_t n )
407 return _wcsupr_s_l( str, n, NULL );
410 /******************************************************************
411 * _wcsupr_l (MSVCRT.@)
413 wchar_t* CDECL _wcsupr_l( wchar_t *str, _locale_t locale )
415 _wcsupr_s_l( str, -1, locale);
416 return str;
419 /******************************************************************
420 * _wcsupr (MSVCRT.@)
422 wchar_t* CDECL _wcsupr( wchar_t *str )
424 return _wcsupr_l(str, NULL);
427 /******************************************************************
428 * _wcslwr_s_l (MSVCRT.@)
430 int CDECL _wcslwr_s_l( wchar_t* str, size_t n, _locale_t locale )
432 _locale_tstruct tmp = {0};
433 wchar_t* ptr = str;
435 if (!str || !n)
437 if (str) *str = '\0';
438 *_errno() = EINVAL;
439 return EINVAL;
442 if(!locale)
443 locale = get_current_locale_noalloc(&tmp);
445 while (n--)
447 if (!*ptr)
449 free_locale_noalloc(&tmp);
450 return 0;
452 *ptr = _towlower_l(*ptr, locale);
453 ptr++;
456 free_locale_noalloc(&tmp);
458 /* MSDN claims that the function should return and set errno to
459 * ERANGE, which doesn't seem to be true based on the tests. */
460 *str = '\0';
461 *_errno() = EINVAL;
462 return EINVAL;
465 /******************************************************************
466 * _wcslwr_s (MSVCRT.@)
468 int CDECL _wcslwr_s( wchar_t* str, size_t n )
470 return _wcslwr_s_l(str, n, NULL);
473 /******************************************************************
474 * _wcslwr_l (MSVCRT.@)
476 wchar_t* CDECL _wcslwr_l( wchar_t* str, _locale_t locale )
478 _wcslwr_s_l(str, -1, locale);
479 return str;
482 /******************************************************************
483 * _wcslwr (MSVCRT.@)
485 wchar_t* CDECL _wcslwr( wchar_t* str )
487 _wcslwr_s_l(str, -1, NULL);
488 return str;
491 /*********************************************************************
492 * wcsncmp (MSVCRT.@)
494 int CDECL wcsncmp(const wchar_t *str1, const wchar_t *str2, size_t n)
496 if (!n)
497 return 0;
498 while(--n && *str1 && (*str1 == *str2))
500 str1++;
501 str2++;
503 return *str1 - *str2;
506 /*********************************************************************
507 * _wcsncoll_l (MSVCRT.@)
509 int CDECL _wcsncoll_l(const wchar_t* str1, const wchar_t* str2,
510 size_t count, _locale_t locale)
512 pthreadlocinfo locinfo;
514 if(!locale)
515 locinfo = get_locinfo();
516 else
517 locinfo = locale->locinfo;
519 if(!locinfo->lc_handle[LC_COLLATE])
520 return wcsncmp(str1, str2, count);
521 return CompareStringW(locinfo->lc_handle[LC_COLLATE], 0,
522 str1, wcsnlen(str1, count),
523 str2, wcsnlen(str2, count))-CSTR_EQUAL;
526 /*********************************************************************
527 * _wcsncoll (MSVCRT.@)
529 int CDECL _wcsncoll(const wchar_t* str1, const wchar_t* str2, size_t count)
531 return _wcsncoll_l(str1, str2, count, NULL);
534 static wchar_t strtod_wstr_get(void *ctx)
536 const wchar_t **p = ctx;
537 if (!**p) return WEOF;
538 return *(*p)++;
541 static void strtod_wstr_unget(void *ctx)
543 const wchar_t **p = ctx;
544 (*p)--;
547 /*********************************************************************
548 * _wcstod_l (MSVCRT.@)
550 double CDECL _wcstod_l(const wchar_t* str, wchar_t** end,
551 _locale_t locale)
553 pthreadlocinfo locinfo;
554 const wchar_t *beg, *p;
555 struct fpnum fp;
556 double ret;
557 int err;
559 if (!MSVCRT_CHECK_PMT(str != NULL)) {
560 if (end) *end = NULL;
561 return 0;
564 if (!locale)
565 locinfo = get_locinfo();
566 else
567 locinfo = locale->locinfo;
569 p = str;
570 while(_iswspace_l(*p, locale))
571 p++;
572 beg = p;
574 fp = fpnum_parse(strtod_wstr_get, strtod_wstr_unget, &p, locinfo, FALSE);
575 if (end) *end = (p == beg ? (wchar_t*)str : (wchar_t*)p);
577 err = fpnum_double(&fp, &ret);
578 if(err) *_errno() = err;
579 return ret;
582 /*********************************************************************
583 * wcsrtombs_l (INTERNAL)
585 static size_t wcsrtombs_l(char *mbstr, const wchar_t **wcstr,
586 size_t count, _locale_t locale)
588 pthreadlocinfo locinfo;
589 size_t tmp = 0;
590 BOOL used_default = FALSE;
591 BOOL *pused_default;
593 if(!locale)
594 locinfo = get_locinfo();
595 else
596 locinfo = locale->locinfo;
598 if(!locinfo->lc_codepage) {
599 size_t i;
601 if(!mbstr)
602 return wcslen(*wcstr);
604 for(i=0; i<count; i++) {
605 if((*wcstr)[i] > 255) {
606 *_errno() = EILSEQ;
607 return -1;
610 mbstr[i] = (*wcstr)[i];
611 if(!(*wcstr)[i]) break;
614 if(i < count) *wcstr = NULL;
615 else *wcstr += i;
616 return i;
619 pused_default = (locinfo->lc_codepage != CP_UTF8 ? &used_default : NULL);
621 if(!mbstr) {
622 tmp = WideCharToMultiByte(locinfo->lc_codepage, WC_NO_BEST_FIT_CHARS,
623 *wcstr, -1, NULL, 0, NULL, pused_default);
624 if(!tmp || used_default) {
625 *_errno() = EILSEQ;
626 return -1;
628 return tmp-1;
631 while(**wcstr) {
632 char buf[3];
633 size_t i, size;
635 size = WideCharToMultiByte(locinfo->lc_codepage, WC_NO_BEST_FIT_CHARS,
636 *wcstr, 1, buf, 3, NULL, pused_default);
637 if(!size || used_default) {
638 *_errno() = EILSEQ;
639 return -1;
641 if(tmp+size > count)
642 return tmp;
644 for(i=0; i<size; i++)
645 mbstr[tmp++] = buf[i];
646 (*wcstr)++;
649 if(tmp < count) {
650 mbstr[tmp] = '\0';
651 *wcstr = NULL;
653 return tmp;
656 /*********************************************************************
657 * _wcstombs_l (MSVCRT.@)
659 size_t CDECL _wcstombs_l(char *mbstr, const wchar_t *wcstr,
660 size_t count, _locale_t locale)
662 return wcsrtombs_l(mbstr, &wcstr, count, locale);
665 /*********************************************************************
666 * wcstombs (MSVCRT.@)
668 size_t CDECL wcstombs(char *mbstr, const wchar_t *wcstr,
669 size_t count)
671 return wcsrtombs_l(mbstr, &wcstr, count, NULL);
674 /*********************************************************************
675 * wcsrtombs (MSVCRT.@)
677 size_t CDECL wcsrtombs(char *mbstr, const wchar_t **wcstr,
678 size_t count, mbstate_t *mbstate)
680 if(mbstate)
681 *mbstate = 0;
683 return wcsrtombs_l(mbstr, wcstr, count, NULL);
686 /*********************************************************************
687 * wcsrtombs_s_l (INTERNAL)
689 static int wcsrtombs_s_l(size_t *ret, char *mbstr, size_t size,
690 const wchar_t **wcstr, size_t count, _locale_t locale)
692 size_t conv;
693 int err;
695 if(!mbstr && !size && wcstr) {
696 conv = wcsrtombs_l(NULL, wcstr, 0, locale);
697 if(ret)
698 *ret = conv+1;
699 if(conv == -1)
700 return *_errno();
701 return 0;
704 if (!MSVCRT_CHECK_PMT(mbstr != NULL)) return EINVAL;
705 if (size) mbstr[0] = '\0';
706 if (!MSVCRT_CHECK_PMT(wcstr != NULL)) return EINVAL;
707 if (!MSVCRT_CHECK_PMT(*wcstr != NULL)) return EINVAL;
709 if(count==_TRUNCATE || size<count)
710 conv = size;
711 else
712 conv = count;
714 err = 0;
715 conv = wcsrtombs_l(mbstr, wcstr, conv, locale);
716 if(conv == -1) {
717 conv = 0;
718 if(size)
719 mbstr[0] = '\0';
720 err = *_errno();
721 }else if(conv < size)
722 mbstr[conv++] = '\0';
723 else if(conv==size && (count==_TRUNCATE || mbstr[conv-1]=='\0')) {
724 mbstr[conv-1] = '\0';
725 if(count==_TRUNCATE)
726 err = STRUNCATE;
727 }else {
728 MSVCRT_INVALID_PMT("mbstr[size] is too small", ERANGE);
729 conv = 0;
730 if(size)
731 mbstr[0] = '\0';
732 err = ERANGE;
735 if(ret)
736 *ret = conv;
737 return err;
740 /*********************************************************************
741 * _wcstombs_s_l (MSVCRT.@)
743 int CDECL _wcstombs_s_l(size_t *ret, char *mbstr, size_t size,
744 const wchar_t *wcstr, size_t count, _locale_t locale)
746 return wcsrtombs_s_l(ret, mbstr, size, &wcstr,count, locale);
749 /*********************************************************************
750 * wcstombs_s (MSVCRT.@)
752 int CDECL wcstombs_s(size_t *ret, char *mbstr, size_t size,
753 const wchar_t *wcstr, size_t count)
755 return wcsrtombs_s_l(ret, mbstr, size, &wcstr, count, NULL);
758 /*********************************************************************
759 * wcsrtombs_s (MSVCRT.@)
761 int CDECL wcsrtombs_s(size_t *ret, char *mbstr, size_t size,
762 const wchar_t **wcstr, size_t count, mbstate_t *mbstate)
764 if(mbstate)
765 *mbstate = 0;
767 return wcsrtombs_s_l(ret, mbstr, size, wcstr, count, NULL);
770 /*********************************************************************
771 * wcstod (MSVCRT.@)
773 double CDECL wcstod(const wchar_t* lpszStr, wchar_t** end)
775 return _wcstod_l(lpszStr, end, NULL);
778 /*********************************************************************
779 * _wtof (MSVCRT.@)
781 double CDECL _wtof(const wchar_t *str)
783 return _wcstod_l(str, NULL, NULL);
786 /*********************************************************************
787 * _wtof_l (MSVCRT.@)
789 double CDECL _wtof_l(const wchar_t *str, _locale_t locale)
791 return _wcstod_l(str, NULL, locale);
794 #if _MSVCR_VER>=120
796 /*********************************************************************
797 * _wcstof_l (MSVCR120.@)
799 float CDECL _wcstof_l( const wchar_t *str, wchar_t **end, _locale_t locale )
801 return _wcstod_l(str, end, locale);
804 /*********************************************************************
805 * wcstof (MSVCR120.@)
807 float CDECL wcstof( const wchar_t *str, wchar_t **end )
809 return _wcstof_l(str, end, NULL);
812 #endif /* _MSVCR_VER>=120 */
814 /*********************************************************************
815 * arg_clbk_valist (INTERNAL)
817 printf_arg arg_clbk_valist(void *ctx, int arg_pos, int type, __ms_va_list *valist)
819 printf_arg ret;
821 if(type == VT_I8)
822 ret.get_longlong = va_arg(*valist, LONGLONG);
823 else if(type == VT_INT)
824 ret.get_int = va_arg(*valist, int);
825 else if(type == VT_R8)
826 ret.get_double = va_arg(*valist, double);
827 else if(type == VT_PTR)
828 ret.get_ptr = va_arg(*valist, void*);
829 else {
830 ERR("Incorrect type\n");
831 ret.get_int = 0;
834 return ret;
837 /*********************************************************************
838 * arg_clbk_positional (INTERNAL)
840 printf_arg arg_clbk_positional(void *ctx, int pos, int type, __ms_va_list *valist)
842 printf_arg *args = ctx;
843 return args[pos];
846 #if _MSVCR_VER < 140
848 /*********************************************************************
849 * _vsnprintf (MSVCRT.@)
851 int CDECL _vsnprintf( char *str, size_t len, const char *format, __ms_va_list valist )
853 static const char nullbyte = '\0';
854 struct _str_ctx_a ctx = {len, str};
855 int ret;
857 ret = pf_printf_a(puts_clbk_str_a, &ctx, format, NULL, 0,
858 arg_clbk_valist, NULL, &valist);
859 puts_clbk_str_a(&ctx, 1, &nullbyte);
860 return ret;
863 #else
865 static int puts_clbk_str_c99_a(void *ctx, int len, const char *str)
867 struct _str_ctx_a *out = ctx;
869 if(!out->buf)
870 return len;
872 if(out->len < len) {
873 memmove(out->buf, str, out->len);
874 out->buf += out->len;
875 out->len = 0;
876 return len;
879 memmove(out->buf, str, len);
880 out->buf += len;
881 out->len -= len;
882 return len;
885 /*********************************************************************
886 * __stdio_common_vsprintf (UCRTBASE.@)
888 int CDECL __stdio_common_vsprintf( unsigned __int64 options, char *str, size_t len, const char *format,
889 _locale_t locale, __ms_va_list valist )
891 static const char nullbyte = '\0';
892 struct _str_ctx_a ctx = {len, str};
893 int ret;
895 if (options & ~UCRTBASE_PRINTF_MASK)
896 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
897 ret = pf_printf_a(puts_clbk_str_c99_a,
898 &ctx, format, (_locale_t)locale, options & UCRTBASE_PRINTF_MASK, arg_clbk_valist, NULL, &valist);
899 puts_clbk_str_a(&ctx, 1, &nullbyte);
901 if(!str)
902 return ret;
903 if(options & _CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION)
904 return ret>len ? -1 : ret;
905 if(ret>=len) {
906 if(len) str[len-1] = 0;
907 if(options & _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR)
908 return ret;
909 return len > 0 ? -2 : -1;
911 return ret;
914 #endif /* _MSVCR_VER>=140 */
916 /*********************************************************************
917 * _vsnprintf_l (MSVCRT.@)
919 int CDECL _vsnprintf_l( char *str, size_t len, const char *format,
920 _locale_t locale, __ms_va_list valist )
922 static const char nullbyte = '\0';
923 struct _str_ctx_a ctx = {len, str};
924 int ret;
926 ret = pf_printf_a(puts_clbk_str_a, &ctx, format, locale, 0,
927 arg_clbk_valist, NULL, &valist);
928 puts_clbk_str_a(&ctx, 1, &nullbyte);
929 return ret;
932 /*********************************************************************
933 * _vsprintf_l (MSVCRT.@)
935 int CDECL _vsprintf_l( char *str, const char *format,
936 _locale_t locale, __ms_va_list valist )
938 return _vsnprintf_l(str, INT_MAX, format, locale, valist);
941 /*********************************************************************
942 * _sprintf_l (MSVCRT.@)
944 int WINAPIV _sprintf_l(char *str, const char *format,
945 _locale_t locale, ...)
947 int retval;
948 __ms_va_list valist;
949 __ms_va_start(valist, locale);
950 retval = _vsnprintf_l(str, INT_MAX, format, locale, valist);
951 __ms_va_end(valist);
952 return retval;
955 static int CDECL vsnprintf_s_l_opt( char *str, size_t sizeOfBuffer,
956 size_t count, const char *format, DWORD options,
957 _locale_t locale, __ms_va_list valist )
959 static const char nullbyte = '\0';
960 struct _str_ctx_a ctx;
961 int len, ret;
963 if(sizeOfBuffer<count+1 || count==-1)
964 len = sizeOfBuffer;
965 else
966 len = count+1;
968 ctx.len = len;
969 ctx.buf = str;
970 ret = pf_printf_a(puts_clbk_str_a, &ctx, format, locale, MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
971 arg_clbk_valist, NULL, &valist);
972 puts_clbk_str_a(&ctx, 1, &nullbyte);
974 if(ret<0 || ret==len) {
975 if(count!=_TRUNCATE && count>sizeOfBuffer) {
976 MSVCRT_INVALID_PMT("str[sizeOfBuffer] is too small", ERANGE);
977 memset(str, 0, sizeOfBuffer);
978 } else
979 str[len-1] = '\0';
981 return -1;
984 return ret;
987 static int vsnwprintf_s_l_opt( wchar_t *str, size_t sizeOfBuffer,
988 size_t count, const wchar_t *format, DWORD options,
989 _locale_t locale, __ms_va_list valist)
991 struct _str_ctx_w ctx;
992 int len, ret;
994 len = sizeOfBuffer;
995 if(count!=-1 && len>count+1)
996 len = count+1;
998 ctx.len = len;
999 ctx.buf = str;
1000 ret = pf_printf_w(puts_clbk_str_w, &ctx, format, locale, MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
1001 arg_clbk_valist, NULL, &valist);
1002 puts_clbk_str_w(&ctx, 1, L"");
1004 if(ret<0 || ret==len) {
1005 if(count!=_TRUNCATE && count>sizeOfBuffer) {
1006 MSVCRT_INVALID_PMT("str[sizeOfBuffer] is too small", ERANGE);
1007 memset(str, 0, sizeOfBuffer*sizeof(wchar_t));
1008 } else
1009 str[len-1] = '\0';
1011 return -1;
1014 return ret;
1017 /*********************************************************************
1018 * _vsnprintf_s_l (MSVCRT.@)
1020 int CDECL _vsnprintf_s_l( char *str, size_t sizeOfBuffer,
1021 size_t count, const char *format,
1022 _locale_t locale, __ms_va_list valist )
1024 return vsnprintf_s_l_opt(str, sizeOfBuffer, count, format, 0, locale, valist);
1027 /*********************************************************************
1028 * _vsprintf_s_l (MSVCRT.@)
1030 int CDECL _vsprintf_s_l( char *str, size_t count, const char *format,
1031 _locale_t locale, __ms_va_list valist )
1033 return _vsnprintf_s_l(str, INT_MAX, count, format, locale, valist);
1036 /*********************************************************************
1037 * _sprintf_s_l (MSVCRT.@)
1039 int WINAPIV _sprintf_s_l( char *str, size_t count, const char *format,
1040 _locale_t locale, ...)
1042 int retval;
1043 __ms_va_list valist;
1044 __ms_va_start(valist, locale);
1045 retval = _vsnprintf_s_l(str, INT_MAX, count, format, locale, valist);
1046 __ms_va_end(valist);
1047 return retval;
1050 /*********************************************************************
1051 * _vsnprintf_s (MSVCRT.@)
1053 int CDECL _vsnprintf_s( char *str, size_t sizeOfBuffer,
1054 size_t count, const char *format, __ms_va_list valist )
1056 return _vsnprintf_s_l(str,sizeOfBuffer, count, format, NULL, valist);
1059 /*********************************************************************
1060 * _vsnprintf_c_l (MSVCRT.@)
1062 int CDECL _vsnprintf_c_l(char *str, size_t len, const char *format,
1063 _locale_t locale, __ms_va_list valist)
1065 return vsnprintf_s_l_opt(str, len, len, format, 0, locale, valist);
1068 /*********************************************************************
1069 * _vsnprintf_c (MSVCRT.@)
1071 int CDECL _vsnprintf_c(char *str, size_t len,
1072 const char *format, __ms_va_list valist)
1074 return _vsnprintf_c_l(str, len, format, NULL, valist);
1077 #if _MSVCR_VER>=140
1079 /*********************************************************************
1080 * __stdio_common_vsnprintf_s (UCRTBASE.@)
1082 int CDECL __stdio_common_vsnprintf_s( unsigned __int64 options,
1083 char *str, size_t sizeOfBuffer, size_t count,
1084 const char *format, _locale_t locale, __ms_va_list valist )
1086 if (options & ~UCRTBASE_PRINTF_MASK)
1087 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
1088 return vsnprintf_s_l_opt(str, sizeOfBuffer, count, format, options & UCRTBASE_PRINTF_MASK, locale, valist);
1091 /*********************************************************************
1092 * __stdio_common_vsnwprintf_s (UCRTBASE.@)
1094 int CDECL __stdio_common_vsnwprintf_s( unsigned __int64 options,
1095 wchar_t *str, size_t sizeOfBuffer, size_t count,
1096 const wchar_t *format, _locale_t locale, __ms_va_list valist )
1098 if (options & ~UCRTBASE_PRINTF_MASK)
1099 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
1100 return vsnwprintf_s_l_opt(str, sizeOfBuffer, count, format, options & UCRTBASE_PRINTF_MASK, locale, valist);
1103 /*********************************************************************
1104 * __stdio_common_vswprintf_s (UCRTBASE.@)
1106 int CDECL __stdio_common_vswprintf_s( unsigned __int64 options,
1107 wchar_t *str, size_t count, const wchar_t *format,
1108 _locale_t locale, __ms_va_list valist )
1110 return __stdio_common_vsnwprintf_s(options, str, INT_MAX, count, format, locale, valist);
1113 /*********************************************************************
1114 * __stdio_common_vsprintf_s (UCRTBASE.@)
1116 int CDECL __stdio_common_vsprintf_s( unsigned __int64 options,
1117 char *str, size_t count, const char *format,
1118 _locale_t locale, __ms_va_list valist )
1120 if (options & ~UCRTBASE_PRINTF_MASK)
1121 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
1122 return vsnprintf_s_l_opt(str, INT_MAX, count, format, options & UCRTBASE_PRINTF_MASK, locale, valist);
1125 #endif /* _MSVCR_VER>=140 */
1127 /*********************************************************************
1128 * vsprintf (MSVCRT.@)
1130 int CDECL vsprintf( char *str, const char *format, __ms_va_list valist)
1132 return vsnprintf(str, INT_MAX, format, valist);
1135 /*********************************************************************
1136 * vsprintf_s (MSVCRT.@)
1138 int CDECL vsprintf_s( char *str, size_t num, const char *format, __ms_va_list valist)
1140 return vsnprintf(str, num, format, valist);
1143 /*********************************************************************
1144 * _vscprintf (MSVCRT.@)
1146 int CDECL _vscprintf( const char *format, __ms_va_list valist )
1148 return _vsnprintf_l( NULL, INT_MAX, format, NULL, valist );
1151 /*********************************************************************
1152 * _vscprintf_l (MSVCRT.@)
1154 int CDECL _vscprintf_l(const char *format,
1155 _locale_t locale, __ms_va_list valist)
1157 return _vsnprintf_l(NULL, INT_MAX, format, locale, valist);
1160 /*********************************************************************
1161 * _vscprintf_p_l (MSVCRT.@)
1163 int CDECL _vscprintf_p_l(const char *format,
1164 _locale_t locale, __ms_va_list args)
1166 printf_arg args_ctx[_ARGMAX+1];
1167 struct _str_ctx_a puts_ctx = {INT_MAX, NULL};
1168 int ret;
1170 memset(args_ctx, 0, sizeof(args_ctx));
1172 ret = create_positional_ctx_a(args_ctx, format, args);
1173 if(ret < 0) {
1174 _invalid_parameter(NULL, NULL, NULL, 0, 0);
1175 *_errno() = EINVAL;
1176 return ret;
1177 } else if(ret == 0) {
1178 ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale,
1179 MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER,
1180 arg_clbk_valist, NULL, &args);
1181 } else {
1182 ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale,
1183 MSVCRT_PRINTF_POSITIONAL_PARAMS | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER,
1184 arg_clbk_positional, args_ctx, NULL);
1187 return ret;
1190 /*********************************************************************
1191 * _vscprintf_p (MSVCR80.@)
1193 int CDECL _vscprintf_p(const char *format, __ms_va_list argptr)
1195 return _vscprintf_p_l(format, NULL, argptr);
1198 /*********************************************************************
1199 * _snprintf (MSVCRT.@)
1201 int WINAPIV _snprintf(char *str, size_t len, const char *format, ...)
1203 int retval;
1204 __ms_va_list valist;
1205 __ms_va_start(valist, format);
1206 retval = vsnprintf(str, len, format, valist);
1207 __ms_va_end(valist);
1208 return retval;
1211 /*********************************************************************
1212 * _snprintf_l (MSVCRT.@)
1214 int WINAPIV _snprintf_l(char *str, size_t count, const char *format,
1215 _locale_t locale, ...)
1217 int retval;
1218 __ms_va_list valist;
1219 __ms_va_start(valist, locale);
1220 retval = _vsnprintf_l(str, count, format, locale, valist);
1221 __ms_va_end(valist);
1222 return retval;
1225 /*********************************************************************
1226 * _snprintf_c_l (MSVCRT.@)
1228 int WINAPIV _snprintf_c_l(char *str, size_t count, const char *format,
1229 _locale_t locale, ...)
1231 int retval;
1232 __ms_va_list valist;
1233 __ms_va_start(valist, locale);
1234 retval = _vsnprintf_c_l(str, count, format, locale, valist);
1235 __ms_va_end(valist);
1236 return retval;
1239 /*********************************************************************
1240 * _snprintf_c (MSVCRT.@)
1242 int WINAPIV _snprintf_c(char *str, size_t count, const char *format, ...)
1244 int retval;
1245 __ms_va_list valist;
1246 __ms_va_start(valist, format);
1247 retval = _vsnprintf_c(str, count, format, valist);
1248 __ms_va_end(valist);
1249 return retval;
1252 /*********************************************************************
1253 * _snprintf_s_l (MSVCRT.@)
1255 int WINAPIV _snprintf_s_l(char *str, size_t len, size_t count,
1256 const char *format, _locale_t locale, ...)
1258 int retval;
1259 __ms_va_list valist;
1260 __ms_va_start(valist, locale);
1261 retval = _vsnprintf_s_l(str, len, count, format, locale, valist);
1262 __ms_va_end(valist);
1263 return retval;
1266 /*********************************************************************
1267 * _snprintf_s (MSVCRT.@)
1269 int WINAPIV _snprintf_s(char *str, size_t len, size_t count,
1270 const char *format, ...)
1272 int retval;
1273 __ms_va_list valist;
1274 __ms_va_start(valist, format);
1275 retval = _vsnprintf_s_l(str, len, count, format, NULL, valist);
1276 __ms_va_end(valist);
1277 return retval;
1280 /*********************************************************************
1281 * _scprintf (MSVCRT.@)
1283 int WINAPIV _scprintf(const char *format, ...)
1285 int retval;
1286 __ms_va_list valist;
1287 __ms_va_start(valist, format);
1288 retval = _vscprintf(format, valist);
1289 __ms_va_end(valist);
1290 return retval;
1293 /*********************************************************************
1294 * _vsnwprintf (MSVCRT.@)
1296 int CDECL _vsnwprintf(wchar_t *str, size_t len,
1297 const wchar_t *format, __ms_va_list valist)
1299 struct _str_ctx_w ctx = {len, str};
1300 int ret;
1302 ret = pf_printf_w(puts_clbk_str_w, &ctx, format, NULL, 0,
1303 arg_clbk_valist, NULL, &valist);
1304 puts_clbk_str_w(&ctx, 1, L"");
1305 return ret;
1308 /*********************************************************************
1309 * _vsnwprintf_l (MSVCRT.@)
1311 int CDECL _vsnwprintf_l(wchar_t *str, size_t len, const wchar_t *format,
1312 _locale_t locale, __ms_va_list valist)
1314 struct _str_ctx_w ctx = {len, str};
1315 int ret;
1317 ret = pf_printf_w(puts_clbk_str_w, &ctx, format, locale, 0,
1318 arg_clbk_valist, NULL, &valist);
1319 puts_clbk_str_w(&ctx, 1, L"");
1320 return ret;
1323 /*********************************************************************
1324 * _vswprintf_c_l (MSVCRT.@)
1326 int CDECL _vswprintf_c_l(wchar_t *str, size_t len, const wchar_t *format,
1327 _locale_t locale, __ms_va_list valist)
1329 return vsnwprintf_s_l_opt(str, len, len, format, 0, locale, valist);
1332 /*********************************************************************
1333 * _vswprintf_c (MSVCRT.@)
1335 int CDECL _vswprintf_c(wchar_t *str, size_t len,
1336 const wchar_t *format, __ms_va_list valist)
1338 return _vswprintf_c_l(str, len, format, NULL, valist);
1341 static int vswprintf_p_l_opt(wchar_t *buffer, size_t length,
1342 const wchar_t *format, DWORD options, _locale_t locale, __ms_va_list args)
1344 printf_arg args_ctx[_ARGMAX+1];
1345 struct _str_ctx_w puts_ctx = {length, buffer};
1346 int ret;
1348 memset(args_ctx, 0, sizeof(args_ctx));
1350 ret = create_positional_ctx_w(args_ctx, format, args);
1351 if(ret < 0) {
1352 _invalid_parameter(NULL, NULL, NULL, 0, 0);
1353 *_errno() = EINVAL;
1354 return ret;
1355 } else if(ret == 0)
1356 ret = pf_printf_w(puts_clbk_str_w, &puts_ctx, format, locale, MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
1357 arg_clbk_valist, NULL, &args);
1358 else
1359 ret = pf_printf_w(puts_clbk_str_w, &puts_ctx, format, locale,
1360 MSVCRT_PRINTF_POSITIONAL_PARAMS | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
1361 arg_clbk_positional, args_ctx, NULL);
1363 puts_clbk_str_w(&puts_ctx, 1, L"");
1364 return ret;
1367 /*********************************************************************
1368 * _vswprintf_p_l (MSVCRT.@)
1370 int CDECL _vswprintf_p_l(wchar_t *buffer, size_t length,
1371 const wchar_t *format, _locale_t locale, __ms_va_list args)
1373 return vswprintf_p_l_opt(buffer, length, format, 0, locale, args);
1376 #if _MSVCR_VER>=80
1377 /*********************************************************************
1378 * _vswprintf_p (MSVCR80.@)
1380 int CDECL _vswprintf_p(wchar_t *buffer, size_t length,
1381 const wchar_t *format, __ms_va_list args)
1383 return vswprintf_p_l_opt(buffer, length, format, 0, NULL, args);
1385 #endif
1387 #if _MSVCR_VER>=140
1388 /*********************************************************************
1389 * __stdio_common_vswprintf_p (UCRTBASE.@)
1391 int CDECL __stdio_common_vswprintf_p( unsigned __int64 options,
1392 wchar_t *str, size_t count, const wchar_t *format,
1393 _locale_t locale, __ms_va_list valist )
1395 if (options & ~UCRTBASE_PRINTF_MASK)
1396 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
1397 return vswprintf_p_l_opt(str, count, format, options & UCRTBASE_PRINTF_MASK, locale, valist);
1399 #endif
1401 /*********************************************************************
1402 * _vsnwprintf_s_l (MSVCRT.@)
1404 int CDECL _vsnwprintf_s_l( wchar_t *str, size_t sizeOfBuffer,
1405 size_t count, const wchar_t *format,
1406 _locale_t locale, __ms_va_list valist)
1408 return vsnwprintf_s_l_opt(str, sizeOfBuffer, count, format, 0, locale, valist);
1411 /*********************************************************************
1412 * _vsnwprintf_s (MSVCRT.@)
1414 int CDECL _vsnwprintf_s(wchar_t *str, size_t sizeOfBuffer,
1415 size_t count, const wchar_t *format, __ms_va_list valist)
1417 return _vsnwprintf_s_l(str, sizeOfBuffer, count,
1418 format, NULL, valist);
1421 /*********************************************************************
1422 * _snwprintf (MSVCRT.@)
1424 int WINAPIV _snwprintf( wchar_t *str, size_t len, const wchar_t *format, ...)
1426 int retval;
1427 __ms_va_list valist;
1428 __ms_va_start(valist, format);
1429 retval = _vsnwprintf(str, len, format, valist);
1430 __ms_va_end(valist);
1431 return retval;
1434 /*********************************************************************
1435 * _snwprintf_l (MSVCRT.@)
1437 int WINAPIV _snwprintf_l( wchar_t *str, size_t len, const wchar_t *format,
1438 _locale_t locale, ...)
1440 int retval;
1441 __ms_va_list valist;
1442 __ms_va_start(valist, locale);
1443 retval = _vsnwprintf_l(str, len, format, locale, valist);
1444 __ms_va_end(valist);
1445 return retval;
1448 /*********************************************************************
1449 * _snwprintf_s (MSVCRT.@)
1451 int WINAPIV _snwprintf_s( wchar_t *str, size_t len, size_t count,
1452 const wchar_t *format, ...)
1454 int retval;
1455 __ms_va_list valist;
1456 __ms_va_start(valist, format);
1457 retval = _vsnwprintf_s_l(str, len, count, format, NULL, valist);
1458 __ms_va_end(valist);
1459 return retval;
1462 /*********************************************************************
1463 * _snwprintf_s_l (MSVCRT.@)
1465 int WINAPIV _snwprintf_s_l( wchar_t *str, size_t len, size_t count,
1466 const wchar_t *format, _locale_t locale, ... )
1468 int retval;
1469 __ms_va_list valist;
1470 __ms_va_start(valist, locale);
1471 retval = _vsnwprintf_s_l(str, len, count, format, locale, valist);
1472 __ms_va_end(valist);
1473 return retval;
1476 #if _MSVCR_VER>=140
1478 static int puts_clbk_str_c99_w(void *ctx, int len, const wchar_t *str)
1480 struct _str_ctx_w *out = ctx;
1482 if(!out->buf)
1483 return len;
1485 if(out->len < len) {
1486 memcpy(out->buf, str, out->len*sizeof(wchar_t));
1487 out->buf += out->len;
1488 out->len = 0;
1489 return len;
1492 memcpy(out->buf, str, len*sizeof(wchar_t));
1493 out->buf += len;
1494 out->len -= len;
1495 return len;
1498 /*********************************************************************
1499 * __stdio_common_vswprintf (UCRTBASE.@)
1501 int CDECL __stdio_common_vswprintf( unsigned __int64 options,
1502 wchar_t *str, size_t len, const wchar_t *format,
1503 _locale_t locale, __ms_va_list valist )
1505 struct _str_ctx_w ctx = {len, str};
1506 int ret;
1508 if (options & ~UCRTBASE_PRINTF_MASK)
1509 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
1510 ret = pf_printf_w(puts_clbk_str_c99_w,
1511 &ctx, format, locale, options & UCRTBASE_PRINTF_MASK, arg_clbk_valist, NULL, &valist);
1512 puts_clbk_str_w(&ctx, 1, L"");
1514 if(!str)
1515 return ret;
1516 if(options & _CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION)
1517 return ret>len ? -1 : ret;
1518 if(ret>=len) {
1519 if(len) str[len-1] = 0;
1520 if(options & _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR)
1521 return ret;
1522 return len > 0 ? -2 : -1;
1524 return ret;
1527 #endif /* _MSVCR_VER>=140 */
1529 /*********************************************************************
1530 * sprintf (MSVCRT.@)
1532 int WINAPIV sprintf( char *str, const char *format, ... )
1534 __ms_va_list ap;
1535 int r;
1537 __ms_va_start( ap, format );
1538 r = vsnprintf( str, INT_MAX, format, ap );
1539 __ms_va_end( ap );
1540 return r;
1543 /*********************************************************************
1544 * sprintf_s (MSVCRT.@)
1546 int WINAPIV sprintf_s( char *str, size_t num, const char *format, ... )
1548 __ms_va_list ap;
1549 int r;
1551 __ms_va_start( ap, format );
1552 r = vsnprintf( str, num, format, ap );
1553 __ms_va_end( ap );
1554 return r;
1557 /*********************************************************************
1558 * _scwprintf (MSVCRT.@)
1560 int WINAPIV _scwprintf( const wchar_t *format, ... )
1562 __ms_va_list ap;
1563 int r;
1565 __ms_va_start( ap, format );
1566 r = _vsnwprintf( NULL, INT_MAX, format, ap );
1567 __ms_va_end( ap );
1568 return r;
1571 /*********************************************************************
1572 * swprintf (MSVCRT.@)
1574 int WINAPIV _swprintf( wchar_t *str, const wchar_t *format, ... )
1576 __ms_va_list ap;
1577 int r;
1579 __ms_va_start( ap, format );
1580 r = _vsnwprintf( str, INT_MAX, format, ap );
1581 __ms_va_end( ap );
1582 return r;
1585 /*********************************************************************
1586 * swprintf_s (MSVCRT.@)
1588 int WINAPIV swprintf_s(wchar_t *str, size_t numberOfElements,
1589 const wchar_t *format, ... )
1591 __ms_va_list ap;
1592 int r;
1594 __ms_va_start(ap, format);
1595 r = _vsnwprintf_s(str, numberOfElements, INT_MAX, format, ap);
1596 __ms_va_end(ap);
1598 return r;
1601 /*********************************************************************
1602 * _swprintf_s_l (MSVCRT.@)
1604 int WINAPIV _swprintf_s_l(wchar_t *str, size_t numberOfElements,
1605 const wchar_t *format, _locale_t locale, ... )
1607 __ms_va_list ap;
1608 int r;
1610 __ms_va_start(ap, locale);
1611 r = _vsnwprintf_s_l(str, numberOfElements, INT_MAX, format, locale, ap);
1612 __ms_va_end(ap);
1614 return r;
1617 /*********************************************************************
1618 * _swprintf_c_l (MSVCRT.@)
1620 int WINAPIV _swprintf_c_l(wchar_t *str, size_t len,
1621 const wchar_t *format, _locale_t locale, ... )
1623 __ms_va_list ap;
1624 int r;
1626 __ms_va_start(ap, locale);
1627 r = _vswprintf_c_l(str, len, format, locale, ap);
1628 __ms_va_end(ap);
1630 return r;
1633 /*********************************************************************
1634 * _swprintf_c (MSVCRT.@)
1636 int WINAPIV _swprintf_c(wchar_t *str, size_t len,
1637 const wchar_t *format, ... )
1639 __ms_va_list ap;
1640 int r;
1642 __ms_va_start(ap, format);
1643 r = _vswprintf_c(str, len, format, ap);
1644 __ms_va_end(ap);
1646 return r;
1649 /*********************************************************************
1650 * _vswprintf (MSVCRT.@)
1652 int CDECL _vswprintf( wchar_t* str, const wchar_t* format, __ms_va_list args )
1654 return _vsnwprintf( str, INT_MAX, format, args );
1657 /*********************************************************************
1658 * _vswprintf (MSVCRT.@)
1660 int CDECL _vswprintf_l( wchar_t* str, const wchar_t* format,
1661 _locale_t locale, __ms_va_list args )
1663 return _vsnwprintf_l( str, INT_MAX, format, locale, args );
1666 /*********************************************************************
1667 * _vscwprintf (MSVCRT.@)
1669 int CDECL _vscwprintf( const wchar_t *format, __ms_va_list args )
1671 return _vsnwprintf( NULL, INT_MAX, format, args );
1674 /*********************************************************************
1675 * _vscwprintf_l (MSVCRT.@)
1677 int CDECL _vscwprintf_l( const wchar_t *format, _locale_t locale, __ms_va_list args )
1679 return _vsnwprintf_l( NULL, INT_MAX, format, locale, args );
1682 /*********************************************************************
1683 * _vscwprintf_p_l (MSVCRT.@)
1685 int CDECL _vscwprintf_p_l( const wchar_t *format, _locale_t locale, __ms_va_list args )
1687 return vswprintf_p_l_opt( NULL, INT_MAX, format, 0, locale, args );
1690 #if _MSVCR_VER>=80
1691 /*********************************************************************
1692 * _vscwprintf_p (MSVCR80.@)
1694 int CDECL _vscwprintf_p(const wchar_t *format, __ms_va_list args)
1696 return vswprintf_p_l_opt(NULL, INT_MAX, format, 0, NULL, args);
1698 #endif
1700 /*********************************************************************
1701 * vswprintf_s (MSVCRT.@)
1703 int CDECL vswprintf_s(wchar_t* str, size_t numberOfElements,
1704 const wchar_t* format, __ms_va_list args)
1706 return _vsnwprintf_s(str, numberOfElements, INT_MAX, format, args );
1709 /*********************************************************************
1710 * _vswprintf_s_l (MSVCRT.@)
1712 int CDECL _vswprintf_s_l(wchar_t* str, size_t numberOfElements,
1713 const wchar_t* format, _locale_t locale, __ms_va_list args)
1715 return _vsnwprintf_s_l(str, numberOfElements, INT_MAX,
1716 format, locale, args );
1719 static int vsprintf_p_l_opt(char *buffer, size_t length, const char *format,
1720 DWORD options, _locale_t locale, __ms_va_list args)
1722 static const char nullbyte = '\0';
1723 printf_arg args_ctx[_ARGMAX+1];
1724 struct _str_ctx_a puts_ctx = {length, buffer};
1725 int ret;
1727 memset(args_ctx, 0, sizeof(args_ctx));
1729 ret = create_positional_ctx_a(args_ctx, format, args);
1730 if(ret < 0) {
1731 _invalid_parameter(NULL, NULL, NULL, 0, 0);
1732 *_errno() = EINVAL;
1733 return ret;
1734 } else if(ret == 0)
1735 ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale,
1736 MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options, arg_clbk_valist, NULL, &args);
1737 else
1738 ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale,
1739 MSVCRT_PRINTF_POSITIONAL_PARAMS | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
1740 arg_clbk_positional, args_ctx, NULL);
1742 puts_clbk_str_a(&puts_ctx, 1, &nullbyte);
1743 return ret;
1746 /*********************************************************************
1747 * _vsprintf_p_l (MSVCRT.@)
1749 int CDECL _vsprintf_p_l(char *buffer, size_t length, const char *format,
1750 _locale_t locale, __ms_va_list args)
1752 return vsprintf_p_l_opt(buffer, length, format, 0, locale, args);
1755 /*********************************************************************
1756 * _vsprintf_p (MSVCRT.@)
1758 int CDECL _vsprintf_p(char *buffer, size_t length,
1759 const char *format, __ms_va_list args)
1761 return _vsprintf_p_l(buffer, length, format, NULL, args);
1764 #if _MSVCR_VER>=140
1765 /*********************************************************************
1766 * __stdio_common_vsprintf_p (UCRTBASE.@)
1768 int CDECL __stdio_common_vsprintf_p(unsigned __int64 options, char *buffer, size_t length,
1769 const char *format, _locale_t locale, __ms_va_list args)
1771 if (options & ~UCRTBASE_PRINTF_MASK)
1772 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
1773 return vsprintf_p_l_opt(buffer, length, format, options & UCRTBASE_PRINTF_MASK, locale, args);
1775 #endif
1777 /*********************************************************************
1778 * _sprintf_p_l (MSVCRT.@)
1780 int WINAPIV _sprintf_p_l(char *buffer, size_t length,
1781 const char *format, _locale_t locale, ...)
1783 __ms_va_list valist;
1784 int r;
1786 __ms_va_start(valist, locale);
1787 r = _vsprintf_p_l(buffer, length, format, locale, valist);
1788 __ms_va_end(valist);
1790 return r;
1793 /*********************************************************************
1794 * __swprintf_l (MSVCRT.@)
1796 int WINAPIV __swprintf_l( wchar_t *str, const wchar_t *format,
1797 _locale_t locale, ...)
1799 int retval;
1800 __ms_va_list valist;
1801 __ms_va_start(valist, locale);
1802 retval = _vswprintf_l(str, format, locale, valist);
1803 __ms_va_end(valist);
1804 return retval;
1807 #if _MSVCR_VER>=80
1808 /*********************************************************************
1809 * _sprintf_p (MSVCR80.@)
1811 int WINAPIV _sprintf_p(char *buffer, size_t length, const char *format, ...)
1813 __ms_va_list valist;
1814 int r;
1816 __ms_va_start(valist, format);
1817 r = _vsprintf_p_l(buffer, length, format, NULL, valist);
1818 __ms_va_end(valist);
1820 return r;
1822 #endif
1824 /*********************************************************************
1825 * _swprintf_p_l (MSVCRT.@)
1827 int WINAPIV _swprintf_p_l(wchar_t *buffer, size_t length,
1828 const wchar_t *format, _locale_t locale, ...)
1830 __ms_va_list valist;
1831 int r;
1833 __ms_va_start(valist, locale);
1834 r = vswprintf_p_l_opt(buffer, length, format, 0, locale, valist);
1835 __ms_va_end(valist);
1837 return r;
1840 /*********************************************************************
1841 * wcscmp (MSVCRT.@)
1843 int CDECL wcscmp(const wchar_t *str1, const wchar_t *str2)
1845 while (*str1 && (*str1 == *str2))
1847 str1++;
1848 str2++;
1851 if (*str1 < *str2)
1852 return -1;
1853 if (*str1 > *str2)
1854 return 1;
1855 return 0;
1858 /*********************************************************************
1859 * _wcscoll_l (MSVCRT.@)
1861 int CDECL _wcscoll_l(const wchar_t* str1, const wchar_t* str2, _locale_t locale)
1863 pthreadlocinfo locinfo;
1865 if(!locale)
1866 locinfo = get_locinfo();
1867 else
1868 locinfo = locale->locinfo;
1870 if(!locinfo->lc_handle[LC_COLLATE])
1871 return wcscmp(str1, str2);
1872 return CompareStringW(locinfo->lc_handle[LC_COLLATE], 0, str1, -1, str2, -1)-CSTR_EQUAL;
1875 /*********************************************************************
1876 * wcscoll (MSVCRT.@)
1878 int CDECL wcscoll( const wchar_t* str1, const wchar_t* str2 )
1880 return _wcscoll_l(str1, str2, NULL);
1883 /*********************************************************************
1884 * wcspbrk (MSVCRT.@)
1886 wchar_t* CDECL wcspbrk( const wchar_t* str, const wchar_t* accept )
1888 const wchar_t* p;
1890 while (*str)
1892 for (p = accept; *p; p++) if (*p == *str) return (wchar_t*)str;
1893 str++;
1895 return NULL;
1898 /*********************************************************************
1899 * wcstok_s (MSVCRT.@)
1901 wchar_t * CDECL wcstok_s( wchar_t *str, const wchar_t *delim,
1902 wchar_t **next_token )
1904 wchar_t *ret;
1906 if (!MSVCRT_CHECK_PMT(delim != NULL)) return NULL;
1907 if (!MSVCRT_CHECK_PMT(next_token != NULL)) return NULL;
1908 if (!MSVCRT_CHECK_PMT(str != NULL || *next_token != NULL)) return NULL;
1910 if (!str) str = *next_token;
1912 while (*str && wcschr( delim, *str )) str++;
1913 if (!*str) return NULL;
1914 ret = str++;
1915 while (*str && !wcschr( delim, *str )) str++;
1916 if (*str) *str++ = 0;
1917 *next_token = str;
1918 return ret;
1921 /*********************************************************************
1922 * wcstok (MSVCRT.@)
1924 #if _MSVCR_VER>=140
1925 wchar_t * CDECL wcstok( wchar_t *str, const wchar_t *delim, wchar_t **ctx )
1927 if (!ctx)
1928 ctx = &msvcrt_get_thread_data()->wcstok_next;
1929 return wcstok_s(str, delim, ctx);
1931 #else
1932 wchar_t * CDECL wcstok( wchar_t *str, const wchar_t *delim )
1934 return wcstok_s(str, delim, &msvcrt_get_thread_data()->wcstok_next);
1936 #endif
1938 /*********************************************************************
1939 * _wctomb_s_l (MSVCRT.@)
1941 int CDECL _wctomb_s_l(int *len, char *mbchar, size_t size,
1942 wchar_t wch, _locale_t locale)
1944 pthreadlocinfo locinfo;
1945 BOOL error = FALSE;
1946 BOOL *perror;
1947 int mblen;
1949 if(!mbchar && size>0) {
1950 if(len)
1951 *len = 0;
1952 return 0;
1955 if(len)
1956 *len = -1;
1958 if(!MSVCRT_CHECK_PMT(size <= INT_MAX))
1959 return EINVAL;
1961 if(!locale)
1962 locinfo = get_locinfo();
1963 else
1964 locinfo = locale->locinfo;
1966 if(!locinfo->lc_codepage) {
1967 if(wch > 0xff) {
1968 if(mbchar && size>0)
1969 memset(mbchar, 0, size);
1970 *_errno() = EILSEQ;
1971 return EILSEQ;
1974 if(!MSVCRT_CHECK_PMT_ERR(size >= 1, ERANGE))
1975 return ERANGE;
1977 *mbchar = wch;
1978 if(len)
1979 *len = 1;
1980 return 0;
1983 perror = (locinfo->lc_codepage != CP_UTF8 ? &error : NULL);
1984 mblen = WideCharToMultiByte(locinfo->lc_codepage, 0, &wch, 1, mbchar, size, NULL, perror);
1985 if(!mblen || error) {
1986 if(!mblen && GetLastError()==ERROR_INSUFFICIENT_BUFFER) {
1987 if(mbchar && size>0)
1988 memset(mbchar, 0, size);
1990 MSVCRT_INVALID_PMT("insufficient buffer size", ERANGE);
1991 return ERANGE;
1994 *_errno() = EILSEQ;
1995 return EILSEQ;
1998 if(len)
1999 *len = mblen;
2000 return 0;
2003 /*********************************************************************
2004 * wctomb_s (MSVCRT.@)
2006 int CDECL wctomb_s(int *len, char *mbchar, size_t size, wchar_t wch)
2008 return _wctomb_s_l(len, mbchar, size, wch, NULL);
2011 /*********************************************************************
2012 * _wctomb_l (MSVCRT.@)
2014 int CDECL _wctomb_l(char *dst, wchar_t ch, _locale_t locale)
2016 int len;
2018 _wctomb_s_l(&len, dst, dst ? MB_LEN_MAX : 0, ch, locale);
2019 return len;
2022 /*********************************************************************
2023 * wctomb (MSVCRT.@)
2025 INT CDECL wctomb( char *dst, wchar_t ch )
2027 return _wctomb_l(dst, ch, NULL);
2030 /*********************************************************************
2031 * wctob (MSVCRT.@)
2033 INT CDECL wctob( wint_t wchar )
2035 char out;
2036 BOOL error = FALSE;
2037 BOOL *perror;
2038 UINT codepage = get_locinfo()->lc_codepage;
2040 perror = (codepage != CP_UTF8 ? &error : NULL);
2042 if(!codepage) {
2043 if (wchar < 0xff)
2044 return (signed char)wchar;
2045 else
2046 return EOF;
2047 } else if(WideCharToMultiByte( codepage, 0, &wchar, 1, &out, 1, NULL, perror ) && !error)
2048 return (INT)out;
2049 return EOF;
2052 /*********************************************************************
2053 * wcrtomb_s (MSVCRT.@)
2055 INT CDECL wcrtomb_s(size_t *len, char *mbchar,
2056 size_t size, wchar_t wch, mbstate_t *s)
2058 int ilen, ret;
2060 if (s) *s = 0;
2061 ret = wctomb_s(&ilen, mbchar, size, wch);
2062 if (len) *len = ilen;
2063 return ret;
2066 /*********************************************************************
2067 * wcrtomb (MSVCRT.@)
2069 size_t CDECL wcrtomb( char *dst, wchar_t ch, mbstate_t *s)
2071 if(s)
2072 *s = 0;
2073 return wctomb(dst, ch);
2076 /*********************************************************************
2077 * _iswctype_l (MSVCRT.@)
2079 INT CDECL _iswctype_l( wchar_t wc, wctype_t type, _locale_t locale )
2081 WORD ct;
2083 if (wc == WEOF) return 0;
2084 if (wc < 256) return MSVCRT__pwctype[wc] & type;
2086 if (!GetStringTypeW(CT_CTYPE1, &wc, 1, &ct))
2088 ERR("GetStringTypeW failed for %x\n", wc);
2089 return 0;
2091 return ct & type;
2094 /*********************************************************************
2095 * iswctype (MSVCRT.@)
2097 INT CDECL iswctype( wchar_t wc, wctype_t type )
2099 return _iswctype_l( wc, type, NULL );
2102 /*********************************************************************
2103 * _iswalnum_l (MSVCRT.@)
2105 int CDECL _iswalnum_l( wchar_t wc, _locale_t locale )
2107 return _iswctype_l( wc, _ALPHA | _DIGIT, locale );
2110 /*********************************************************************
2111 * iswalnum (MSVCRT.@)
2113 INT CDECL iswalnum( wchar_t wc )
2115 return _iswalnum_l( wc, NULL );
2118 /*********************************************************************
2119 * iswalpha_l (MSVCRT.@)
2121 INT CDECL _iswalpha_l( wchar_t wc, _locale_t locale )
2123 return _iswctype_l( wc, _ALPHA, locale );
2126 /*********************************************************************
2127 * iswalpha (MSVCRT.@)
2129 INT CDECL iswalpha( wchar_t wc )
2131 return _iswalpha_l( wc, NULL );
2134 /*********************************************************************
2135 * _iswcntrl_l (MSVCRT.@)
2137 int CDECL _iswcntrl_l( wchar_t wc, _locale_t locale )
2139 return _iswctype_l( wc, _CONTROL, locale );
2142 /*********************************************************************
2143 * iswcntrl (MSVCRT.@)
2145 INT CDECL iswcntrl( wchar_t wc )
2147 return _iswcntrl_l( wc, NULL );
2150 /*********************************************************************
2151 * _iswdigit_l (MSVCRT.@)
2153 INT CDECL _iswdigit_l( wchar_t wc, _locale_t locale )
2155 return _iswctype_l( wc, _DIGIT, locale );
2158 /*********************************************************************
2159 * iswdigit (MSVCRT.@)
2161 INT CDECL iswdigit( wchar_t wc )
2163 return _iswdigit_l( wc, NULL );
2166 /*********************************************************************
2167 * _iswgraph_l (MSVCRT.@)
2169 int CDECL _iswgraph_l( wchar_t wc, _locale_t locale )
2171 return _iswctype_l( wc, _ALPHA | _DIGIT | _PUNCT, locale );
2174 /*********************************************************************
2175 * iswgraph (MSVCRT.@)
2177 INT CDECL iswgraph( wchar_t wc )
2179 return _iswgraph_l( wc, NULL );
2182 /*********************************************************************
2183 * _iswlower_l (MSVCRT.@)
2185 int CDECL _iswlower_l( wchar_t wc, _locale_t locale )
2187 return _iswctype_l( wc, _LOWER, locale );
2190 /*********************************************************************
2191 * iswlower (MSVCRT.@)
2193 INT CDECL iswlower( wchar_t wc )
2195 return _iswlower_l( wc, NULL );
2198 /*********************************************************************
2199 * _iswprint_l (MSVCRT.@)
2201 int CDECL _iswprint_l( wchar_t wc, _locale_t locale )
2203 return _iswctype_l( wc, _ALPHA | _BLANK | _DIGIT | _PUNCT, locale );
2206 /*********************************************************************
2207 * iswprint (MSVCRT.@)
2209 INT CDECL iswprint( wchar_t wc )
2211 return _iswprint_l( wc, NULL );
2214 /*********************************************************************
2215 * _iswpunct_l (MSVCRT.@)
2217 INT CDECL _iswpunct_l( wchar_t wc, _locale_t locale )
2219 return _iswctype_l( wc, _PUNCT, locale );
2222 /*********************************************************************
2223 * iswpunct (MSVCRT.@)
2225 INT CDECL iswpunct( wchar_t wc )
2227 return _iswpunct_l( wc, NULL );
2230 /*********************************************************************
2231 * _iswspace_l (MSVCRT.@)
2233 INT CDECL _iswspace_l( wchar_t wc, _locale_t locale )
2235 return _iswctype_l( wc, _SPACE, locale );
2238 /*********************************************************************
2239 * iswspace (MSVCRT.@)
2241 INT CDECL iswspace( wchar_t wc )
2243 return _iswspace_l( wc, NULL );
2246 /*********************************************************************
2247 * _iswupper_l (MSVCRT.@)
2249 int CDECL _iswupper_l( wchar_t wc, _locale_t locale )
2251 return _iswctype_l( wc, _UPPER, locale );
2254 /*********************************************************************
2255 * iswupper (MSVCRT.@)
2257 INT CDECL iswupper( wchar_t wc )
2259 return _iswupper_l( wc, NULL );
2262 /*********************************************************************
2263 * _iswxdigit_l (MSVCRT.@)
2265 int CDECL _iswxdigit_l( wchar_t wc, _locale_t locale )
2267 return _iswctype_l( wc, _HEX, locale );
2270 /*********************************************************************
2271 * iswxdigit (MSVCRT.@)
2273 INT CDECL iswxdigit( wchar_t wc )
2275 return _iswxdigit_l( wc, NULL );
2278 /*********************************************************************
2279 * _iswblank_l (MSVCRT.@)
2281 INT CDECL _iswblank_l( wchar_t wc, _locale_t locale )
2283 return wc == '\t' || _iswctype_l( wc, _BLANK, locale );
2286 /*********************************************************************
2287 * iswblank (MSVCRT.@)
2289 INT CDECL iswblank( wchar_t wc )
2291 return wc == '\t' || _iswctype_l( wc, _BLANK, NULL );
2294 /*********************************************************************
2295 * wcscpy_s (MSVCRT.@)
2297 INT CDECL wcscpy_s( wchar_t* wcDest, size_t numElement, const wchar_t *wcSrc)
2299 size_t size = 0;
2301 if(!MSVCRT_CHECK_PMT(wcDest)) return EINVAL;
2302 if(!MSVCRT_CHECK_PMT(numElement)) return EINVAL;
2304 if(!MSVCRT_CHECK_PMT(wcSrc))
2306 wcDest[0] = 0;
2307 return EINVAL;
2310 size = wcslen(wcSrc) + 1;
2312 if(!MSVCRT_CHECK_PMT_ERR(size <= numElement, ERANGE))
2314 wcDest[0] = 0;
2315 return ERANGE;
2318 memmove( wcDest, wcSrc, size*sizeof(WCHAR) );
2320 return 0;
2323 /***********************************************************************
2324 * wcscpy (MSVCRT.@)
2326 wchar_t* __cdecl wcscpy( wchar_t *dst, const wchar_t *src )
2328 WCHAR *p = dst;
2329 while ((*p++ = *src++));
2330 return dst;
2333 /******************************************************************
2334 * wcsncpy (MSVCRT.@)
2336 wchar_t* __cdecl wcsncpy( wchar_t* s1, const wchar_t *s2, size_t n )
2338 size_t i;
2340 for(i=0; i<n; i++)
2341 if(!(s1[i] = s2[i])) break;
2342 for(; i<n; i++)
2343 s1[i] = 0;
2344 return s1;
2347 /******************************************************************
2348 * wcsncpy_s (MSVCRT.@)
2350 INT CDECL wcsncpy_s( wchar_t* wcDest, size_t numElement, const wchar_t *wcSrc,
2351 size_t count )
2353 WCHAR *p = wcDest;
2354 BOOL truncate = (count == _TRUNCATE);
2356 if(!wcDest && !numElement && !count)
2357 return 0;
2359 if (!wcDest || !numElement)
2360 return EINVAL;
2362 if (!wcSrc)
2364 *wcDest = 0;
2365 return count ? EINVAL : 0;
2368 while (numElement && count && *wcSrc)
2370 *p++ = *wcSrc++;
2371 numElement--;
2372 count--;
2374 if (!numElement && truncate)
2376 *(p-1) = 0;
2377 return STRUNCATE;
2379 else if (!numElement)
2381 *wcDest = 0;
2382 return ERANGE;
2385 *p = 0;
2386 return 0;
2389 /******************************************************************
2390 * wcscat_s (MSVCRT.@)
2393 INT CDECL wcscat_s(wchar_t* dst, size_t elem, const wchar_t* src)
2395 wchar_t* ptr = dst;
2397 if (!dst || elem == 0) return EINVAL;
2398 if (!src)
2400 dst[0] = '\0';
2401 return EINVAL;
2404 /* seek to end of dst string (or elem if no end of string is found */
2405 while (ptr < dst + elem && *ptr != '\0') ptr++;
2406 while (ptr < dst + elem)
2408 if ((*ptr++ = *src++) == '\0') return 0;
2410 /* not enough space */
2411 dst[0] = '\0';
2412 return ERANGE;
2415 /***********************************************************************
2416 * wcscat (MSVCRT.@)
2418 wchar_t* __cdecl wcscat( wchar_t *dst, const wchar_t *src )
2420 wcscpy( dst + wcslen(dst), src );
2421 return dst;
2424 /*********************************************************************
2425 * wcsncat_s (MSVCRT.@)
2428 INT CDECL wcsncat_s(wchar_t *dst, size_t elem,
2429 const wchar_t *src, size_t count)
2431 size_t srclen;
2432 wchar_t dststart;
2433 INT ret = 0;
2435 if (!MSVCRT_CHECK_PMT(dst != NULL)) return EINVAL;
2436 if (!MSVCRT_CHECK_PMT(elem > 0)) return EINVAL;
2437 if (!MSVCRT_CHECK_PMT(src != NULL || count == 0)) return EINVAL;
2439 if (count == 0)
2440 return 0;
2442 for (dststart = 0; dststart < elem; dststart++)
2444 if (dst[dststart] == '\0')
2445 break;
2447 if (dststart == elem)
2449 MSVCRT_INVALID_PMT("dst[elem] is not NULL terminated\n", EINVAL);
2450 return EINVAL;
2453 if (count == _TRUNCATE)
2455 srclen = wcslen(src);
2456 if (srclen >= (elem - dststart))
2458 srclen = elem - dststart - 1;
2459 ret = STRUNCATE;
2462 else
2463 srclen = min(wcslen(src), count);
2464 if (srclen < (elem - dststart))
2466 memcpy(&dst[dststart], src, srclen*sizeof(wchar_t));
2467 dst[dststart+srclen] = '\0';
2468 return ret;
2470 MSVCRT_INVALID_PMT("dst[elem] is too small", ERANGE);
2471 dst[0] = '\0';
2472 return ERANGE;
2475 /*********************************************************************
2476 * wctoint (INTERNAL)
2478 static int wctoint(WCHAR c, int base)
2480 int v = -1;
2481 if ('0' <= c && c <= '9')
2482 v = c - '0';
2483 else if ('A' <= c && c <= 'Z')
2484 v = c - 'A' + 10;
2485 else if ('a' <= c && c <= 'z')
2486 v = c - 'a' + 10;
2487 else {
2488 /* NOTE: wine_fold_string(MAP_FOLDDIGITS) supports too many things. */
2489 /* Unicode points that contain digits 0-9; keep this sorted! */
2490 static const WCHAR zeros[] = {
2491 0x660, 0x6f0, 0x966, 0x9e6, 0xa66, 0xae6, 0xb66, 0xc66, 0xce6,
2492 0xd66, 0xe50, 0xed0, 0xf20, 0x1040, 0x17e0, 0x1810, 0xff10
2494 int i;
2495 for (i = 0; i < ARRAY_SIZE(zeros) && c >= zeros[i]; ++i) {
2496 if (zeros[i] <= c && c <= zeros[i] + 9) {
2497 v = c - zeros[i];
2498 break;
2502 return v < base ? v : -1;
2505 /*********************************************************************
2506 * _wcstoi64_l (MSVCRT.@)
2508 __int64 CDECL _wcstoi64_l(const wchar_t *nptr,
2509 wchar_t **endptr, int base, _locale_t locale)
2511 BOOL negative = FALSE, empty = TRUE;
2512 __int64 ret = 0;
2514 TRACE("(%s %p %d %p)\n", debugstr_w(nptr), endptr, base, locale);
2516 if (!MSVCRT_CHECK_PMT(nptr != NULL)) return 0;
2517 if (!MSVCRT_CHECK_PMT(base == 0 || base >= 2)) return 0;
2518 if (!MSVCRT_CHECK_PMT(base <= 36)) return 0;
2520 if(endptr)
2521 *endptr = (wchar_t*)nptr;
2523 while(_iswspace_l(*nptr, locale)) nptr++;
2525 if(*nptr == '-') {
2526 negative = TRUE;
2527 nptr++;
2528 } else if(*nptr == '+')
2529 nptr++;
2531 if((base==0 || base==16) && wctoint(*nptr, 1)==0 && (nptr[1]=='x' || nptr[1]=='X')) {
2532 base = 16;
2533 nptr += 2;
2536 if(base == 0) {
2537 if(wctoint(*nptr, 1)==0)
2538 base = 8;
2539 else
2540 base = 10;
2543 while(*nptr) {
2544 int v = wctoint(*nptr, base);
2545 if(v<0)
2546 break;
2548 if(negative)
2549 v = -v;
2551 nptr++;
2552 empty = FALSE;
2554 if(!negative && (ret>I64_MAX/base || ret*base>I64_MAX-v)) {
2555 ret = I64_MAX;
2556 *_errno() = ERANGE;
2557 } else if(negative && (ret<I64_MIN/base || ret*base<I64_MIN-v)) {
2558 ret = I64_MIN;
2559 *_errno() = ERANGE;
2560 } else
2561 ret = ret*base + v;
2564 if(endptr && !empty)
2565 *endptr = (wchar_t*)nptr;
2567 return ret;
2570 /*********************************************************************
2571 * _wcstoi64 (MSVCRT.@)
2573 __int64 CDECL _wcstoi64(const wchar_t *nptr,
2574 wchar_t **endptr, int base)
2576 return _wcstoi64_l(nptr, endptr, base, NULL);
2579 /*********************************************************************
2580 * _wcstol_l (MSVCRT.@)
2582 __msvcrt_long CDECL _wcstol_l(const wchar_t *s,
2583 wchar_t **end, int base, _locale_t locale)
2585 __int64 ret = _wcstoi64_l(s, end, base, locale);
2587 if(ret > LONG_MAX) {
2588 ret = LONG_MAX;
2589 *_errno() = ERANGE;
2590 }else if(ret < LONG_MIN) {
2591 ret = LONG_MIN;
2592 *_errno() = ERANGE;
2594 return ret;
2597 /*********************************************************************
2598 * wcstol (MSVCRT.@)
2600 __msvcrt_long CDECL wcstol(const wchar_t *s,
2601 wchar_t **end, int base)
2603 return _wcstol_l(s, end, base, NULL);
2606 /*********************************************************************
2607 * _wtoi_l (MSVCRT.@)
2609 int __cdecl _wtoi_l(const wchar_t *str, _locale_t locale)
2611 __int64 ret = _wcstoi64_l(str, NULL, 10, locale);
2613 if(ret > INT_MAX) {
2614 ret = INT_MAX;
2615 *_errno() = ERANGE;
2616 } else if(ret < INT_MIN) {
2617 ret = INT_MIN;
2618 *_errno() = ERANGE;
2620 return ret;
2623 /*********************************************************************
2624 * _wtoi (MSVCRT.@)
2626 int __cdecl _wtoi(const wchar_t *str)
2628 return _wtoi_l(str, NULL);
2631 /*********************************************************************
2632 * _wtol_l (MSVCRT.@)
2634 __msvcrt_long __cdecl _wtol_l(const wchar_t *str, _locale_t locale)
2636 __int64 ret = _wcstoi64_l(str, NULL, 10, locale);
2638 if(ret > LONG_MAX) {
2639 ret = LONG_MAX;
2640 *_errno() = ERANGE;
2641 } else if(ret < LONG_MIN) {
2642 ret = LONG_MIN;
2643 *_errno() = ERANGE;
2645 return ret;
2648 /*********************************************************************
2649 * _wtol (MSVCRT.@)
2651 __msvcrt_long __cdecl _wtol(const wchar_t *str)
2653 return _wtol_l(str, NULL);
2656 #if _MSVCR_VER>=120
2658 /*********************************************************************
2659 * _wtoll_l (MSVCR120.@)
2661 __int64 __cdecl _wtoll_l(const wchar_t *str, _locale_t locale)
2663 return _wcstoi64_l(str, NULL, 10, locale);
2666 /*********************************************************************
2667 * _wtoll (MSVCR120.@)
2669 __int64 __cdecl _wtoll(const wchar_t *str)
2671 return _wtoll_l(str, NULL);
2674 #endif /* _MSVCR_VER>=120 */
2676 /*********************************************************************
2677 * _wcstoui64_l (MSVCRT.@)
2679 unsigned __int64 CDECL _wcstoui64_l(const wchar_t *nptr,
2680 wchar_t **endptr, int base, _locale_t locale)
2682 BOOL negative = FALSE, empty = TRUE;
2683 unsigned __int64 ret = 0;
2685 TRACE("(%s %p %d %p)\n", debugstr_w(nptr), endptr, base, locale);
2687 if (!MSVCRT_CHECK_PMT(nptr != NULL)) return 0;
2688 if (!MSVCRT_CHECK_PMT(base == 0 || base >= 2)) return 0;
2689 if (!MSVCRT_CHECK_PMT(base <= 36)) return 0;
2691 if(endptr)
2692 *endptr = (wchar_t*)nptr;
2694 while(_iswspace_l(*nptr, locale)) nptr++;
2696 if(*nptr == '-') {
2697 negative = TRUE;
2698 nptr++;
2699 } else if(*nptr == '+')
2700 nptr++;
2702 if((base==0 || base==16) && wctoint(*nptr, 1)==0 && (nptr[1]=='x' || nptr[1]=='X')) {
2703 base = 16;
2704 nptr += 2;
2707 if(base == 0) {
2708 if(wctoint(*nptr, 1)==0)
2709 base = 8;
2710 else
2711 base = 10;
2714 while(*nptr) {
2715 int v = wctoint(*nptr, base);
2716 if(v<0)
2717 break;
2719 nptr++;
2720 empty = FALSE;
2722 if(ret>UI64_MAX/base || ret*base>UI64_MAX-v) {
2723 ret = UI64_MAX;
2724 *_errno() = ERANGE;
2725 } else
2726 ret = ret*base + v;
2729 if(endptr && !empty)
2730 *endptr = (wchar_t*)nptr;
2732 return negative ? -ret : ret;
2735 /*********************************************************************
2736 * _wcstoui64 (MSVCRT.@)
2738 unsigned __int64 CDECL _wcstoui64(const wchar_t *nptr,
2739 wchar_t **endptr, int base)
2741 return _wcstoui64_l(nptr, endptr, base, NULL);
2744 /*********************************************************************
2745 * _wcstoul_l (MSVCRT.@)
2747 __msvcrt_ulong __cdecl _wcstoul_l(const wchar_t *s,
2748 wchar_t **end, int base, _locale_t locale)
2750 __int64 ret = _wcstoi64_l(s, end, base, locale);
2752 if(ret > ULONG_MAX) {
2753 ret = ULONG_MAX;
2754 *_errno() = ERANGE;
2755 }else if(ret < -(__int64)ULONG_MAX) {
2756 ret = 1;
2757 *_errno() = ERANGE;
2759 return ret;
2762 /*********************************************************************
2763 * wcstoul (MSVCRT.@)
2765 __msvcrt_ulong __cdecl wcstoul(const wchar_t *s, wchar_t **end, int base)
2767 return _wcstoul_l(s, end, base, NULL);
2770 /******************************************************************
2771 * wcsnlen (MSVCRT.@)
2773 size_t CDECL wcsnlen(const wchar_t *s, size_t maxlen)
2775 size_t i;
2777 for (i = 0; i < maxlen; i++)
2778 if (!s[i]) break;
2779 return i;
2782 /*********************************************************************
2783 * _towupper_l (MSVCRT.@)
2785 wint_t CDECL _towupper_l(wint_t c, _locale_t locale)
2787 pthreadlocinfo locinfo;
2788 wchar_t ret;
2790 if(!locale)
2791 locinfo = get_locinfo();
2792 else
2793 locinfo = locale->locinfo;
2795 if(!locinfo->lc_handle[LC_CTYPE]) {
2796 if(c >= 'a' && c <= 'z')
2797 return c + 'A' - 'a';
2798 return c;
2801 if(!LCMapStringW(locinfo->lc_handle[LC_CTYPE], LCMAP_UPPERCASE, &c, 1, &ret, 1))
2802 return c;
2803 return ret;
2806 /*********************************************************************
2807 * towupper (MSVCRT.@)
2809 wint_t CDECL towupper(wint_t c)
2811 return _towupper_l(c, NULL);
2814 /*********************************************************************
2815 * wcschr (MSVCRT.@)
2817 wchar_t* CDECL wcschr(const wchar_t *str, wchar_t ch)
2819 do { if (*str == ch) return (WCHAR *)(ULONG_PTR)str; } while (*str++);
2820 return NULL;
2823 /*********************************************************************
2824 * wcsrchr (MSVCRT.@)
2826 wchar_t* CDECL wcsrchr(const wchar_t *str, wchar_t ch)
2828 WCHAR *ret = NULL;
2829 do { if (*str == ch) ret = (WCHAR *)(ULONG_PTR)str; } while (*str++);
2830 return ret;
2833 /***********************************************************************
2834 * wcslen (MSVCRT.@)
2836 size_t CDECL wcslen(const wchar_t *str)
2838 const wchar_t *s = str;
2839 while (*s) s++;
2840 return s - str;
2843 /*********************************************************************
2844 * wcsstr (MSVCRT.@)
2846 wchar_t* CDECL wcsstr(const wchar_t *str, const wchar_t *sub)
2848 while(*str)
2850 const wchar_t *p1 = str, *p2 = sub;
2851 while(*p1 && *p2 && *p1 == *p2)
2853 p1++;
2854 p2++;
2856 if(!*p2)
2857 return (wchar_t*)str;
2858 str++;
2860 return NULL;
2863 /*********************************************************************
2864 * _wtoi64_l (MSVCRT.@)
2866 __int64 CDECL _wtoi64_l(const wchar_t *str, _locale_t locale)
2868 ULONGLONG RunningTotal = 0;
2869 BOOL bMinus = FALSE;
2871 while (_iswspace_l(*str, locale)) {
2872 str++;
2873 } /* while */
2875 if (*str == '+') {
2876 str++;
2877 } else if (*str == '-') {
2878 bMinus = TRUE;
2879 str++;
2880 } /* if */
2882 while (*str >= '0' && *str <= '9') {
2883 RunningTotal = RunningTotal * 10 + *str - '0';
2884 str++;
2885 } /* while */
2887 return bMinus ? -RunningTotal : RunningTotal;
2890 /*********************************************************************
2891 * _wtoi64 (MSVCRT.@)
2893 __int64 CDECL _wtoi64(const wchar_t *str)
2895 return _wtoi64_l(str, NULL);
2898 /*********************************************************************
2899 * _wcsxfrm_l (MSVCRT.@)
2901 size_t CDECL _wcsxfrm_l(wchar_t *dest, const wchar_t *src,
2902 size_t len, _locale_t locale)
2904 pthreadlocinfo locinfo;
2905 int i, ret;
2907 if(!MSVCRT_CHECK_PMT(src)) return INT_MAX;
2908 if(!MSVCRT_CHECK_PMT(dest || !len)) return INT_MAX;
2910 if(len > INT_MAX) {
2911 FIXME("len > INT_MAX not supported\n");
2912 len = INT_MAX;
2915 if(!locale)
2916 locinfo = get_locinfo();
2917 else
2918 locinfo = locale->locinfo;
2920 if(!locinfo->lc_handle[LC_COLLATE]) {
2921 wcsncpy(dest, src, len);
2922 return wcslen(src);
2925 ret = LCMapStringW(locinfo->lc_handle[LC_COLLATE],
2926 LCMAP_SORTKEY, src, -1, NULL, 0);
2927 if(!ret) {
2928 if(len) dest[0] = 0;
2929 *_errno() = EILSEQ;
2930 return INT_MAX;
2932 if(!len) return ret-1;
2934 if(ret > len) {
2935 dest[0] = 0;
2936 *_errno() = ERANGE;
2937 return ret-1;
2940 ret = LCMapStringW(locinfo->lc_handle[LC_COLLATE],
2941 LCMAP_SORTKEY, src, -1, dest, len) - 1;
2942 for(i=ret; i>=0; i--)
2943 dest[i] = ((unsigned char*)dest)[i];
2944 return ret;
2947 /*********************************************************************
2948 * wcsxfrm (MSVCRT.@)
2950 size_t CDECL wcsxfrm(wchar_t *dest, const wchar_t *src, size_t len)
2952 return _wcsxfrm_l(dest, src, len, NULL);