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
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt
);
38 enum { LEN_DEFAULT
, LEN_SHORT
, LEN_LONG
} IntegerLength
;
39 BOOLEAN IntegerDouble
, IntegerNative
, LeftAlign
, Alternate
, PadZero
;
40 BOOLEAN WideString
, NaturalString
;
41 int FieldLength
, Precision
;
45 static BOOL n_format_enabled
= TRUE
;
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;
72 #endif /* _MSVCR_VER>=80 */
74 /*********************************************************************
77 wchar_t* CDECL
_wcsdup( const wchar_t* str
)
82 int size
= (wcslen(str
) + 1) * sizeof(wchar_t);
84 if (ret
) memcpy( ret
, str
, size
);
89 /*********************************************************************
90 * _towlower_l (MSVCRT.@)
92 wint_t CDECL
_towlower_l(wint_t c
, _locale_t locale
)
94 pthreadlocinfo locinfo
;
98 locinfo
= get_locinfo();
100 locinfo
= locale
->locinfo
;
102 if(!locinfo
->lc_handle
[LC_CTYPE
]) {
103 if(c
>= 'A' && c
<= 'Z')
104 return c
+ 'a' - 'A';
108 if(!LCMapStringW(locinfo
->lc_handle
[LC_CTYPE
], LCMAP_LOWERCASE
, &c
, 1, &ret
, 1))
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};
126 if(!MSVCRT_CHECK_PMT(str1
!= NULL
) || !MSVCRT_CHECK_PMT(str2
!= NULL
))
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
);
142 /*********************************************************************
143 * towctrans (MSVCR120.@)
145 wint_t CDECL
towctrans(wint_t c
, wctrans_t category
)
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};
172 if(!MSVCRT_CHECK_PMT(str1
!= NULL
) || !MSVCRT_CHECK_PMT(str2
!= NULL
))
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
);
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
;
204 locinfo
= get_locinfo();
206 locinfo
= locale
->locinfo
;
208 if(!locinfo
->lc_handle
[LC_COLLATE
])
215 if (c1
>= 'A' && c1
<= 'Z')
219 if (c2
>= 'A' && c2
<= 'Z')
221 } while(c1
&& (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
;
246 locinfo
= get_locinfo();
248 locinfo
= locale
->locinfo
;
250 if(!locinfo
->lc_handle
[LC_COLLATE
])
260 if (c1
>= 'A' && c1
<= 'Z')
264 if (c2
>= 'A' && c2
<= 'Z')
266 } while(--count
&& c1
&& (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
)
289 while ((n
-- > 0) && *str
) *str
++ = c
;
293 /*********************************************************************
294 * _wcsnset_s (MSVCRT.@)
296 int CDECL
_wcsnset_s( wchar_t *str
, size_t size
, wchar_t c
, size_t count
)
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;
309 if(!str
[i
]) return 0;
312 _invalid_parameter(NULL
, NULL
, NULL
, 0, 0);
317 /*********************************************************************
320 wchar_t* CDECL
_wcsrev( wchar_t* str
)
323 wchar_t* end
= str
+ wcslen(str
) - 1;
333 /*********************************************************************
334 * _wcsset_s (MSVCRT.@)
336 int CDECL
_wcsset_s( wchar_t *str
, size_t n
, wchar_t c
)
340 if(!MSVCRT_CHECK_PMT(str
!= NULL
)) return EINVAL
;
341 if(!MSVCRT_CHECK_PMT(n
)) return EINVAL
;
343 while(*p
&& --n
) *p
++ = c
;
346 _invalid_parameter(NULL
, NULL
, NULL
, 0, 0);
353 /*********************************************************************
356 wchar_t* CDECL
_wcsset( wchar_t* str
, wchar_t c
)
359 while (*str
) *str
++ = c
;
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};
373 if (str
) *str
= '\0';
379 locale
= get_current_locale_noalloc(&tmp
);
385 free_locale_noalloc(&tmp
);
388 *ptr
= _towupper_l(*ptr
, locale
);
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. */
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
);
419 /******************************************************************
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};
437 if (str
) *str
= '\0';
443 locale
= get_current_locale_noalloc(&tmp
);
449 free_locale_noalloc(&tmp
);
452 *ptr
= _towlower_l(*ptr
, locale
);
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. */
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
);
482 /******************************************************************
485 wchar_t* CDECL
_wcslwr( wchar_t* str
)
487 _wcslwr_s_l(str
, -1, NULL
);
491 /*********************************************************************
494 int CDECL
wcsncmp(const wchar_t *str1
, const wchar_t *str2
, size_t n
)
498 while(--n
&& *str1
&& (*str1
== *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
;
515 locinfo
= get_locinfo();
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
;
541 static void strtod_wstr_unget(void *ctx
)
543 const wchar_t **p
= ctx
;
547 /*********************************************************************
548 * _wcstod_l (MSVCRT.@)
550 double CDECL
_wcstod_l(const wchar_t* str
, wchar_t** end
,
553 pthreadlocinfo locinfo
;
554 const wchar_t *beg
, *p
;
559 if (!MSVCRT_CHECK_PMT(str
!= NULL
)) {
560 if (end
) *end
= NULL
;
565 locinfo
= get_locinfo();
567 locinfo
= locale
->locinfo
;
570 while(_iswspace_l(*p
, locale
))
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
;
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
;
590 BOOL used_default
= FALSE
;
594 locinfo
= get_locinfo();
596 locinfo
= locale
->locinfo
;
598 if(!locinfo
->lc_codepage
) {
602 return wcslen(*wcstr
);
604 for(i
=0; i
<count
; i
++) {
605 if((*wcstr
)[i
] > 255) {
610 mbstr
[i
] = (*wcstr
)[i
];
611 if(!(*wcstr
)[i
]) break;
614 if(i
< count
) *wcstr
= NULL
;
619 pused_default
= (locinfo
->lc_codepage
!= CP_UTF8
? &used_default
: NULL
);
622 tmp
= WideCharToMultiByte(locinfo
->lc_codepage
, WC_NO_BEST_FIT_CHARS
,
623 *wcstr
, -1, NULL
, 0, NULL
, pused_default
);
624 if(!tmp
|| used_default
) {
635 size
= WideCharToMultiByte(locinfo
->lc_codepage
, WC_NO_BEST_FIT_CHARS
,
636 *wcstr
, 1, buf
, 3, NULL
, pused_default
);
637 if(!size
|| used_default
) {
644 for(i
=0; i
<size
; i
++)
645 mbstr
[tmp
++] = buf
[i
];
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
,
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
)
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
)
695 if(!mbstr
&& !size
&& wcstr
) {
696 conv
= wcsrtombs_l(NULL
, wcstr
, 0, locale
);
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
)
715 conv
= wcsrtombs_l(mbstr
, wcstr
, conv
, locale
);
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';
728 MSVCRT_INVALID_PMT("mbstr[size] is too small", ERANGE
);
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
)
767 return wcsrtombs_s_l(ret
, mbstr
, size
, wcstr
, count
, NULL
);
770 /*********************************************************************
773 double CDECL
wcstod(const wchar_t* lpszStr
, wchar_t** end
)
775 return _wcstod_l(lpszStr
, end
, NULL
);
778 /*********************************************************************
781 double CDECL
_wtof(const wchar_t *str
)
783 return _wcstod_l(str
, NULL
, NULL
);
786 /*********************************************************************
789 double CDECL
_wtof_l(const wchar_t *str
, _locale_t locale
)
791 return _wcstod_l(str
, NULL
, locale
);
796 /*********************************************************************
797 * _wcstof_l (MSVCR120.@)
799 float CDECL
_wcstof_l( const wchar_t *str
, wchar_t **end
, _locale_t locale
)
801 double ret
= _wcstod_l(str
, end
, locale
);
802 if (ret
&& isfinite(ret
)) {
804 if (!f
|| !isfinite(f
))
810 /*********************************************************************
811 * wcstof (MSVCR120.@)
813 float CDECL
wcstof( const wchar_t *str
, wchar_t **end
)
815 return _wcstof_l(str
, end
, NULL
);
818 #endif /* _MSVCR_VER>=120 */
820 /*********************************************************************
821 * arg_clbk_valist (INTERNAL)
823 printf_arg
arg_clbk_valist(void *ctx
, int arg_pos
, int type
, __ms_va_list
*valist
)
828 ret
.get_longlong
= va_arg(*valist
, LONGLONG
);
829 else if(type
== VT_INT
)
830 ret
.get_int
= va_arg(*valist
, int);
831 else if(type
== VT_R8
)
832 ret
.get_double
= va_arg(*valist
, double);
833 else if(type
== VT_PTR
)
834 ret
.get_ptr
= va_arg(*valist
, void*);
836 ERR("Incorrect type\n");
843 /*********************************************************************
844 * arg_clbk_positional (INTERNAL)
846 printf_arg
arg_clbk_positional(void *ctx
, int pos
, int type
, __ms_va_list
*valist
)
848 printf_arg
*args
= ctx
;
854 /*********************************************************************
855 * _vsnprintf (MSVCRT.@)
857 int CDECL
_vsnprintf( char *str
, size_t len
, const char *format
, __ms_va_list valist
)
859 static const char nullbyte
= '\0';
860 struct _str_ctx_a ctx
= {len
, str
};
863 ret
= pf_printf_a(puts_clbk_str_a
, &ctx
, format
, NULL
, 0,
864 arg_clbk_valist
, NULL
, &valist
);
865 puts_clbk_str_a(&ctx
, 1, &nullbyte
);
871 static int puts_clbk_str_c99_a(void *ctx
, int len
, const char *str
)
873 struct _str_ctx_a
*out
= ctx
;
879 memmove(out
->buf
, str
, out
->len
);
880 out
->buf
+= out
->len
;
885 memmove(out
->buf
, str
, len
);
891 /*********************************************************************
892 * __stdio_common_vsprintf (UCRTBASE.@)
894 int CDECL
__stdio_common_vsprintf( unsigned __int64 options
, char *str
, size_t len
, const char *format
,
895 _locale_t locale
, __ms_va_list valist
)
897 static const char nullbyte
= '\0';
898 struct _str_ctx_a ctx
= {len
, str
};
901 if (options
& ~UCRTBASE_PRINTF_MASK
)
902 FIXME("options %s not handled\n", wine_dbgstr_longlong(options
));
903 ret
= pf_printf_a(puts_clbk_str_c99_a
,
904 &ctx
, format
, (_locale_t
)locale
, options
& UCRTBASE_PRINTF_MASK
, arg_clbk_valist
, NULL
, &valist
);
905 puts_clbk_str_a(&ctx
, 1, &nullbyte
);
909 if(options
& _CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION
)
910 return ret
>len
? -1 : ret
;
912 if(len
) str
[len
-1] = 0;
913 if(options
& _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR
)
915 return len
> 0 ? -2 : -1;
920 #endif /* _MSVCR_VER>=140 */
922 /*********************************************************************
923 * _vsnprintf_l (MSVCRT.@)
925 int CDECL
_vsnprintf_l( char *str
, size_t len
, const char *format
,
926 _locale_t locale
, __ms_va_list valist
)
928 static const char nullbyte
= '\0';
929 struct _str_ctx_a ctx
= {len
, str
};
932 ret
= pf_printf_a(puts_clbk_str_a
, &ctx
, format
, locale
, 0,
933 arg_clbk_valist
, NULL
, &valist
);
934 puts_clbk_str_a(&ctx
, 1, &nullbyte
);
938 /*********************************************************************
939 * _vsprintf_l (MSVCRT.@)
941 int CDECL
_vsprintf_l( char *str
, const char *format
,
942 _locale_t locale
, __ms_va_list valist
)
944 return _vsnprintf_l(str
, INT_MAX
, format
, locale
, valist
);
947 /*********************************************************************
948 * _sprintf_l (MSVCRT.@)
950 int WINAPIV
_sprintf_l(char *str
, const char *format
,
951 _locale_t locale
, ...)
955 __ms_va_start(valist
, locale
);
956 retval
= _vsnprintf_l(str
, INT_MAX
, format
, locale
, valist
);
961 static int CDECL
vsnprintf_s_l_opt( char *str
, size_t sizeOfBuffer
,
962 size_t count
, const char *format
, DWORD options
,
963 _locale_t locale
, __ms_va_list valist
)
965 static const char nullbyte
= '\0';
966 struct _str_ctx_a ctx
;
969 if(sizeOfBuffer
<count
+1 || count
==-1)
976 ret
= pf_printf_a(puts_clbk_str_a
, &ctx
, format
, locale
, MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER
| options
,
977 arg_clbk_valist
, NULL
, &valist
);
978 puts_clbk_str_a(&ctx
, 1, &nullbyte
);
980 if(ret
<0 || ret
==len
) {
981 if(count
!=_TRUNCATE
&& count
>sizeOfBuffer
) {
982 MSVCRT_INVALID_PMT("str[sizeOfBuffer] is too small", ERANGE
);
983 memset(str
, 0, sizeOfBuffer
);
993 static int vsnwprintf_s_l_opt( wchar_t *str
, size_t sizeOfBuffer
,
994 size_t count
, const wchar_t *format
, DWORD options
,
995 _locale_t locale
, __ms_va_list valist
)
997 struct _str_ctx_w ctx
;
1001 if(count
!=-1 && len
>count
+1)
1006 ret
= pf_printf_w(puts_clbk_str_w
, &ctx
, format
, locale
, MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER
| options
,
1007 arg_clbk_valist
, NULL
, &valist
);
1008 puts_clbk_str_w(&ctx
, 1, L
"");
1010 if(ret
<0 || ret
==len
) {
1011 if(count
!=_TRUNCATE
&& count
>sizeOfBuffer
) {
1012 MSVCRT_INVALID_PMT("str[sizeOfBuffer] is too small", ERANGE
);
1013 memset(str
, 0, sizeOfBuffer
*sizeof(wchar_t));
1023 /*********************************************************************
1024 * _vsnprintf_s_l (MSVCRT.@)
1026 int CDECL
_vsnprintf_s_l( char *str
, size_t sizeOfBuffer
,
1027 size_t count
, const char *format
,
1028 _locale_t locale
, __ms_va_list valist
)
1030 return vsnprintf_s_l_opt(str
, sizeOfBuffer
, count
, format
, 0, locale
, valist
);
1033 /*********************************************************************
1034 * _vsprintf_s_l (MSVCRT.@)
1036 int CDECL
_vsprintf_s_l( char *str
, size_t count
, const char *format
,
1037 _locale_t locale
, __ms_va_list valist
)
1039 return _vsnprintf_s_l(str
, INT_MAX
, count
, format
, locale
, valist
);
1042 /*********************************************************************
1043 * _sprintf_s_l (MSVCRT.@)
1045 int WINAPIV
_sprintf_s_l( char *str
, size_t count
, const char *format
,
1046 _locale_t locale
, ...)
1049 __ms_va_list valist
;
1050 __ms_va_start(valist
, locale
);
1051 retval
= _vsnprintf_s_l(str
, INT_MAX
, count
, format
, locale
, valist
);
1052 __ms_va_end(valist
);
1056 /*********************************************************************
1057 * _vsnprintf_s (MSVCRT.@)
1059 int CDECL
_vsnprintf_s( char *str
, size_t sizeOfBuffer
,
1060 size_t count
, const char *format
, __ms_va_list valist
)
1062 return _vsnprintf_s_l(str
,sizeOfBuffer
, count
, format
, NULL
, valist
);
1065 /*********************************************************************
1066 * _vsnprintf_c_l (MSVCRT.@)
1068 int CDECL
_vsnprintf_c_l(char *str
, size_t len
, const char *format
,
1069 _locale_t locale
, __ms_va_list valist
)
1071 return vsnprintf_s_l_opt(str
, len
, len
, format
, 0, locale
, valist
);
1074 /*********************************************************************
1075 * _vsnprintf_c (MSVCRT.@)
1077 int CDECL
_vsnprintf_c(char *str
, size_t len
,
1078 const char *format
, __ms_va_list valist
)
1080 return _vsnprintf_c_l(str
, len
, format
, NULL
, valist
);
1085 /*********************************************************************
1086 * __stdio_common_vsnprintf_s (UCRTBASE.@)
1088 int CDECL
__stdio_common_vsnprintf_s( unsigned __int64 options
,
1089 char *str
, size_t sizeOfBuffer
, size_t count
,
1090 const char *format
, _locale_t locale
, __ms_va_list valist
)
1092 if (options
& ~UCRTBASE_PRINTF_MASK
)
1093 FIXME("options %s not handled\n", wine_dbgstr_longlong(options
));
1094 return vsnprintf_s_l_opt(str
, sizeOfBuffer
, count
, format
, options
& UCRTBASE_PRINTF_MASK
, locale
, valist
);
1097 /*********************************************************************
1098 * __stdio_common_vsnwprintf_s (UCRTBASE.@)
1100 int CDECL
__stdio_common_vsnwprintf_s( unsigned __int64 options
,
1101 wchar_t *str
, size_t sizeOfBuffer
, size_t count
,
1102 const wchar_t *format
, _locale_t locale
, __ms_va_list valist
)
1104 if (options
& ~UCRTBASE_PRINTF_MASK
)
1105 FIXME("options %s not handled\n", wine_dbgstr_longlong(options
));
1106 return vsnwprintf_s_l_opt(str
, sizeOfBuffer
, count
, format
, options
& UCRTBASE_PRINTF_MASK
, locale
, valist
);
1109 /*********************************************************************
1110 * __stdio_common_vswprintf_s (UCRTBASE.@)
1112 int CDECL
__stdio_common_vswprintf_s( unsigned __int64 options
,
1113 wchar_t *str
, size_t count
, const wchar_t *format
,
1114 _locale_t locale
, __ms_va_list valist
)
1116 return __stdio_common_vsnwprintf_s(options
, str
, INT_MAX
, count
, format
, locale
, valist
);
1119 /*********************************************************************
1120 * __stdio_common_vsprintf_s (UCRTBASE.@)
1122 int CDECL
__stdio_common_vsprintf_s( unsigned __int64 options
,
1123 char *str
, size_t count
, const char *format
,
1124 _locale_t locale
, __ms_va_list valist
)
1126 if (options
& ~UCRTBASE_PRINTF_MASK
)
1127 FIXME("options %s not handled\n", wine_dbgstr_longlong(options
));
1128 return vsnprintf_s_l_opt(str
, INT_MAX
, count
, format
, options
& UCRTBASE_PRINTF_MASK
, locale
, valist
);
1131 #endif /* _MSVCR_VER>=140 */
1133 /*********************************************************************
1134 * vsprintf (MSVCRT.@)
1136 int CDECL
vsprintf( char *str
, const char *format
, __ms_va_list valist
)
1138 return vsnprintf(str
, INT_MAX
, format
, valist
);
1141 /*********************************************************************
1142 * vsprintf_s (MSVCRT.@)
1144 int CDECL
vsprintf_s( char *str
, size_t num
, const char *format
, __ms_va_list valist
)
1146 return vsnprintf(str
, num
, format
, valist
);
1149 /*********************************************************************
1150 * _vscprintf (MSVCRT.@)
1152 int CDECL
_vscprintf( const char *format
, __ms_va_list valist
)
1154 return _vsnprintf_l( NULL
, INT_MAX
, format
, NULL
, valist
);
1157 /*********************************************************************
1158 * _vscprintf_l (MSVCRT.@)
1160 int CDECL
_vscprintf_l(const char *format
,
1161 _locale_t locale
, __ms_va_list valist
)
1163 return _vsnprintf_l(NULL
, INT_MAX
, format
, locale
, valist
);
1166 /*********************************************************************
1167 * _vscprintf_p_l (MSVCRT.@)
1169 int CDECL
_vscprintf_p_l(const char *format
,
1170 _locale_t locale
, __ms_va_list args
)
1172 printf_arg args_ctx
[_ARGMAX
+1];
1173 struct _str_ctx_a puts_ctx
= {INT_MAX
, NULL
};
1176 memset(args_ctx
, 0, sizeof(args_ctx
));
1178 ret
= create_positional_ctx_a(args_ctx
, format
, args
);
1180 _invalid_parameter(NULL
, NULL
, NULL
, 0, 0);
1183 } else if(ret
== 0) {
1184 ret
= pf_printf_a(puts_clbk_str_a
, &puts_ctx
, format
, locale
,
1185 MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER
,
1186 arg_clbk_valist
, NULL
, &args
);
1188 ret
= pf_printf_a(puts_clbk_str_a
, &puts_ctx
, format
, locale
,
1189 MSVCRT_PRINTF_POSITIONAL_PARAMS
| MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER
,
1190 arg_clbk_positional
, args_ctx
, NULL
);
1196 /*********************************************************************
1197 * _vscprintf_p (MSVCR80.@)
1199 int CDECL
_vscprintf_p(const char *format
, __ms_va_list argptr
)
1201 return _vscprintf_p_l(format
, NULL
, argptr
);
1204 /*********************************************************************
1205 * _snprintf (MSVCRT.@)
1207 int WINAPIV
_snprintf(char *str
, size_t len
, const char *format
, ...)
1210 __ms_va_list valist
;
1211 __ms_va_start(valist
, format
);
1212 retval
= vsnprintf(str
, len
, format
, valist
);
1213 __ms_va_end(valist
);
1217 /*********************************************************************
1218 * _snprintf_l (MSVCRT.@)
1220 int WINAPIV
_snprintf_l(char *str
, size_t count
, const char *format
,
1221 _locale_t locale
, ...)
1224 __ms_va_list valist
;
1225 __ms_va_start(valist
, locale
);
1226 retval
= _vsnprintf_l(str
, count
, format
, locale
, valist
);
1227 __ms_va_end(valist
);
1231 /*********************************************************************
1232 * _snprintf_c_l (MSVCRT.@)
1234 int WINAPIV
_snprintf_c_l(char *str
, size_t count
, const char *format
,
1235 _locale_t locale
, ...)
1238 __ms_va_list valist
;
1239 __ms_va_start(valist
, locale
);
1240 retval
= _vsnprintf_c_l(str
, count
, format
, locale
, valist
);
1241 __ms_va_end(valist
);
1245 /*********************************************************************
1246 * _snprintf_c (MSVCRT.@)
1248 int WINAPIV
_snprintf_c(char *str
, size_t count
, const char *format
, ...)
1251 __ms_va_list valist
;
1252 __ms_va_start(valist
, format
);
1253 retval
= _vsnprintf_c(str
, count
, format
, valist
);
1254 __ms_va_end(valist
);
1258 /*********************************************************************
1259 * _snprintf_s_l (MSVCRT.@)
1261 int WINAPIV
_snprintf_s_l(char *str
, size_t len
, size_t count
,
1262 const char *format
, _locale_t locale
, ...)
1265 __ms_va_list valist
;
1266 __ms_va_start(valist
, locale
);
1267 retval
= _vsnprintf_s_l(str
, len
, count
, format
, locale
, valist
);
1268 __ms_va_end(valist
);
1272 /*********************************************************************
1273 * _snprintf_s (MSVCRT.@)
1275 int WINAPIV
_snprintf_s(char *str
, size_t len
, size_t count
,
1276 const char *format
, ...)
1279 __ms_va_list valist
;
1280 __ms_va_start(valist
, format
);
1281 retval
= _vsnprintf_s_l(str
, len
, count
, format
, NULL
, valist
);
1282 __ms_va_end(valist
);
1286 /*********************************************************************
1287 * _scprintf (MSVCRT.@)
1289 int WINAPIV
_scprintf(const char *format
, ...)
1292 __ms_va_list valist
;
1293 __ms_va_start(valist
, format
);
1294 retval
= _vscprintf(format
, valist
);
1295 __ms_va_end(valist
);
1299 /*********************************************************************
1300 * _vsnwprintf (MSVCRT.@)
1302 int CDECL
_vsnwprintf(wchar_t *str
, size_t len
,
1303 const wchar_t *format
, __ms_va_list valist
)
1305 struct _str_ctx_w ctx
= {len
, str
};
1308 ret
= pf_printf_w(puts_clbk_str_w
, &ctx
, format
, NULL
, 0,
1309 arg_clbk_valist
, NULL
, &valist
);
1310 puts_clbk_str_w(&ctx
, 1, L
"");
1314 /*********************************************************************
1315 * _vsnwprintf_l (MSVCRT.@)
1317 int CDECL
_vsnwprintf_l(wchar_t *str
, size_t len
, const wchar_t *format
,
1318 _locale_t locale
, __ms_va_list valist
)
1320 struct _str_ctx_w ctx
= {len
, str
};
1323 ret
= pf_printf_w(puts_clbk_str_w
, &ctx
, format
, locale
, 0,
1324 arg_clbk_valist
, NULL
, &valist
);
1325 puts_clbk_str_w(&ctx
, 1, L
"");
1329 /*********************************************************************
1330 * _vswprintf_c_l (MSVCRT.@)
1332 int CDECL
_vswprintf_c_l(wchar_t *str
, size_t len
, const wchar_t *format
,
1333 _locale_t locale
, __ms_va_list valist
)
1335 return vsnwprintf_s_l_opt(str
, len
, len
, format
, 0, locale
, valist
);
1338 /*********************************************************************
1339 * _vswprintf_c (MSVCRT.@)
1341 int CDECL
_vswprintf_c(wchar_t *str
, size_t len
,
1342 const wchar_t *format
, __ms_va_list valist
)
1344 return _vswprintf_c_l(str
, len
, format
, NULL
, valist
);
1347 static int vswprintf_p_l_opt(wchar_t *buffer
, size_t length
,
1348 const wchar_t *format
, DWORD options
, _locale_t locale
, __ms_va_list args
)
1350 printf_arg args_ctx
[_ARGMAX
+1];
1351 struct _str_ctx_w puts_ctx
= {length
, buffer
};
1354 memset(args_ctx
, 0, sizeof(args_ctx
));
1356 ret
= create_positional_ctx_w(args_ctx
, format
, args
);
1358 _invalid_parameter(NULL
, NULL
, NULL
, 0, 0);
1362 ret
= pf_printf_w(puts_clbk_str_w
, &puts_ctx
, format
, locale
, MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER
| options
,
1363 arg_clbk_valist
, NULL
, &args
);
1365 ret
= pf_printf_w(puts_clbk_str_w
, &puts_ctx
, format
, locale
,
1366 MSVCRT_PRINTF_POSITIONAL_PARAMS
| MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER
| options
,
1367 arg_clbk_positional
, args_ctx
, NULL
);
1369 puts_clbk_str_w(&puts_ctx
, 1, L
"");
1373 /*********************************************************************
1374 * _vswprintf_p_l (MSVCRT.@)
1376 int CDECL
_vswprintf_p_l(wchar_t *buffer
, size_t length
,
1377 const wchar_t *format
, _locale_t locale
, __ms_va_list args
)
1379 return vswprintf_p_l_opt(buffer
, length
, format
, 0, locale
, args
);
1383 /*********************************************************************
1384 * _vswprintf_p (MSVCR80.@)
1386 int CDECL
_vswprintf_p(wchar_t *buffer
, size_t length
,
1387 const wchar_t *format
, __ms_va_list args
)
1389 return vswprintf_p_l_opt(buffer
, length
, format
, 0, NULL
, args
);
1394 /*********************************************************************
1395 * __stdio_common_vswprintf_p (UCRTBASE.@)
1397 int CDECL
__stdio_common_vswprintf_p( unsigned __int64 options
,
1398 wchar_t *str
, size_t count
, const wchar_t *format
,
1399 _locale_t locale
, __ms_va_list valist
)
1401 if (options
& ~UCRTBASE_PRINTF_MASK
)
1402 FIXME("options %s not handled\n", wine_dbgstr_longlong(options
));
1403 return vswprintf_p_l_opt(str
, count
, format
, options
& UCRTBASE_PRINTF_MASK
, locale
, valist
);
1407 /*********************************************************************
1408 * _vsnwprintf_s_l (MSVCRT.@)
1410 int CDECL
_vsnwprintf_s_l( wchar_t *str
, size_t sizeOfBuffer
,
1411 size_t count
, const wchar_t *format
,
1412 _locale_t locale
, __ms_va_list valist
)
1414 return vsnwprintf_s_l_opt(str
, sizeOfBuffer
, count
, format
, 0, locale
, valist
);
1417 /*********************************************************************
1418 * _vsnwprintf_s (MSVCRT.@)
1420 int CDECL
_vsnwprintf_s(wchar_t *str
, size_t sizeOfBuffer
,
1421 size_t count
, const wchar_t *format
, __ms_va_list valist
)
1423 return _vsnwprintf_s_l(str
, sizeOfBuffer
, count
,
1424 format
, NULL
, valist
);
1427 /*********************************************************************
1428 * _snwprintf (MSVCRT.@)
1430 int WINAPIV
_snwprintf( wchar_t *str
, size_t len
, const wchar_t *format
, ...)
1433 __ms_va_list valist
;
1434 __ms_va_start(valist
, format
);
1435 retval
= _vsnwprintf(str
, len
, format
, valist
);
1436 __ms_va_end(valist
);
1440 /*********************************************************************
1441 * _snwprintf_l (MSVCRT.@)
1443 int WINAPIV
_snwprintf_l( wchar_t *str
, size_t len
, const wchar_t *format
,
1444 _locale_t locale
, ...)
1447 __ms_va_list valist
;
1448 __ms_va_start(valist
, locale
);
1449 retval
= _vsnwprintf_l(str
, len
, format
, locale
, valist
);
1450 __ms_va_end(valist
);
1454 /*********************************************************************
1455 * _snwprintf_s (MSVCRT.@)
1457 int WINAPIV
_snwprintf_s( wchar_t *str
, size_t len
, size_t count
,
1458 const wchar_t *format
, ...)
1461 __ms_va_list valist
;
1462 __ms_va_start(valist
, format
);
1463 retval
= _vsnwprintf_s_l(str
, len
, count
, format
, NULL
, valist
);
1464 __ms_va_end(valist
);
1468 /*********************************************************************
1469 * _snwprintf_s_l (MSVCRT.@)
1471 int WINAPIV
_snwprintf_s_l( wchar_t *str
, size_t len
, size_t count
,
1472 const wchar_t *format
, _locale_t locale
, ... )
1475 __ms_va_list valist
;
1476 __ms_va_start(valist
, locale
);
1477 retval
= _vsnwprintf_s_l(str
, len
, count
, format
, locale
, valist
);
1478 __ms_va_end(valist
);
1484 static int puts_clbk_str_c99_w(void *ctx
, int len
, const wchar_t *str
)
1486 struct _str_ctx_w
*out
= ctx
;
1491 if(out
->len
< len
) {
1492 memcpy(out
->buf
, str
, out
->len
*sizeof(wchar_t));
1493 out
->buf
+= out
->len
;
1498 memcpy(out
->buf
, str
, len
*sizeof(wchar_t));
1504 /*********************************************************************
1505 * __stdio_common_vswprintf (UCRTBASE.@)
1507 int CDECL
__stdio_common_vswprintf( unsigned __int64 options
,
1508 wchar_t *str
, size_t len
, const wchar_t *format
,
1509 _locale_t locale
, __ms_va_list valist
)
1511 struct _str_ctx_w ctx
= {len
, str
};
1514 if (options
& ~UCRTBASE_PRINTF_MASK
)
1515 FIXME("options %s not handled\n", wine_dbgstr_longlong(options
));
1516 ret
= pf_printf_w(puts_clbk_str_c99_w
,
1517 &ctx
, format
, locale
, options
& UCRTBASE_PRINTF_MASK
, arg_clbk_valist
, NULL
, &valist
);
1518 puts_clbk_str_w(&ctx
, 1, L
"");
1522 if(options
& _CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION
)
1523 return ret
>len
? -1 : ret
;
1525 if(len
) str
[len
-1] = 0;
1526 if(options
& _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR
)
1528 return len
> 0 ? -2 : -1;
1533 #endif /* _MSVCR_VER>=140 */
1535 /*********************************************************************
1536 * sprintf (MSVCRT.@)
1538 int WINAPIV
sprintf( char *str
, const char *format
, ... )
1543 __ms_va_start( ap
, format
);
1544 r
= vsnprintf( str
, INT_MAX
, format
, ap
);
1549 /*********************************************************************
1550 * sprintf_s (MSVCRT.@)
1552 int WINAPIV
sprintf_s( char *str
, size_t num
, const char *format
, ... )
1557 __ms_va_start( ap
, format
);
1558 r
= vsnprintf( str
, num
, format
, ap
);
1563 /*********************************************************************
1564 * _scwprintf (MSVCRT.@)
1566 int WINAPIV
_scwprintf( const wchar_t *format
, ... )
1571 __ms_va_start( ap
, format
);
1572 r
= _vsnwprintf( NULL
, INT_MAX
, format
, ap
);
1577 /*********************************************************************
1578 * swprintf (MSVCRT.@)
1580 int WINAPIV
_swprintf( wchar_t *str
, const wchar_t *format
, ... )
1585 __ms_va_start( ap
, format
);
1586 r
= _vsnwprintf( str
, INT_MAX
, format
, ap
);
1591 /*********************************************************************
1592 * swprintf_s (MSVCRT.@)
1594 int WINAPIV
swprintf_s(wchar_t *str
, size_t numberOfElements
,
1595 const wchar_t *format
, ... )
1600 __ms_va_start(ap
, format
);
1601 r
= _vsnwprintf_s(str
, numberOfElements
, INT_MAX
, format
, ap
);
1607 /*********************************************************************
1608 * _swprintf_s_l (MSVCRT.@)
1610 int WINAPIV
_swprintf_s_l(wchar_t *str
, size_t numberOfElements
,
1611 const wchar_t *format
, _locale_t locale
, ... )
1616 __ms_va_start(ap
, locale
);
1617 r
= _vsnwprintf_s_l(str
, numberOfElements
, INT_MAX
, format
, locale
, ap
);
1623 /*********************************************************************
1624 * _swprintf_c_l (MSVCRT.@)
1626 int WINAPIV
_swprintf_c_l(wchar_t *str
, size_t len
,
1627 const wchar_t *format
, _locale_t locale
, ... )
1632 __ms_va_start(ap
, locale
);
1633 r
= _vswprintf_c_l(str
, len
, format
, locale
, ap
);
1639 /*********************************************************************
1640 * _swprintf_c (MSVCRT.@)
1642 int WINAPIV
_swprintf_c(wchar_t *str
, size_t len
,
1643 const wchar_t *format
, ... )
1648 __ms_va_start(ap
, format
);
1649 r
= _vswprintf_c(str
, len
, format
, ap
);
1655 /*********************************************************************
1656 * _vswprintf (MSVCRT.@)
1658 int CDECL
_vswprintf( wchar_t* str
, const wchar_t* format
, __ms_va_list args
)
1660 return _vsnwprintf( str
, INT_MAX
, format
, args
);
1663 /*********************************************************************
1664 * _vswprintf (MSVCRT.@)
1666 int CDECL
_vswprintf_l( wchar_t* str
, const wchar_t* format
,
1667 _locale_t locale
, __ms_va_list args
)
1669 return _vsnwprintf_l( str
, INT_MAX
, format
, locale
, args
);
1672 /*********************************************************************
1673 * _vscwprintf (MSVCRT.@)
1675 int CDECL
_vscwprintf( const wchar_t *format
, __ms_va_list args
)
1677 return _vsnwprintf( NULL
, INT_MAX
, format
, args
);
1680 /*********************************************************************
1681 * _vscwprintf_l (MSVCRT.@)
1683 int CDECL
_vscwprintf_l( const wchar_t *format
, _locale_t locale
, __ms_va_list args
)
1685 return _vsnwprintf_l( NULL
, INT_MAX
, format
, locale
, args
);
1688 /*********************************************************************
1689 * _vscwprintf_p_l (MSVCRT.@)
1691 int CDECL
_vscwprintf_p_l( const wchar_t *format
, _locale_t locale
, __ms_va_list args
)
1693 return vswprintf_p_l_opt( NULL
, INT_MAX
, format
, 0, locale
, args
);
1697 /*********************************************************************
1698 * _vscwprintf_p (MSVCR80.@)
1700 int CDECL
_vscwprintf_p(const wchar_t *format
, __ms_va_list args
)
1702 return vswprintf_p_l_opt(NULL
, INT_MAX
, format
, 0, NULL
, args
);
1706 /*********************************************************************
1707 * vswprintf_s (MSVCRT.@)
1709 int CDECL
vswprintf_s(wchar_t* str
, size_t numberOfElements
,
1710 const wchar_t* format
, __ms_va_list args
)
1712 return _vsnwprintf_s(str
, numberOfElements
, INT_MAX
, format
, args
);
1715 /*********************************************************************
1716 * _vswprintf_s_l (MSVCRT.@)
1718 int CDECL
_vswprintf_s_l(wchar_t* str
, size_t numberOfElements
,
1719 const wchar_t* format
, _locale_t locale
, __ms_va_list args
)
1721 return _vsnwprintf_s_l(str
, numberOfElements
, INT_MAX
,
1722 format
, locale
, args
);
1725 static int vsprintf_p_l_opt(char *buffer
, size_t length
, const char *format
,
1726 DWORD options
, _locale_t locale
, __ms_va_list args
)
1728 static const char nullbyte
= '\0';
1729 printf_arg args_ctx
[_ARGMAX
+1];
1730 struct _str_ctx_a puts_ctx
= {length
, buffer
};
1733 memset(args_ctx
, 0, sizeof(args_ctx
));
1735 ret
= create_positional_ctx_a(args_ctx
, format
, args
);
1737 _invalid_parameter(NULL
, NULL
, NULL
, 0, 0);
1741 ret
= pf_printf_a(puts_clbk_str_a
, &puts_ctx
, format
, locale
,
1742 MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER
| options
, arg_clbk_valist
, NULL
, &args
);
1744 ret
= pf_printf_a(puts_clbk_str_a
, &puts_ctx
, format
, locale
,
1745 MSVCRT_PRINTF_POSITIONAL_PARAMS
| MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER
| options
,
1746 arg_clbk_positional
, args_ctx
, NULL
);
1748 puts_clbk_str_a(&puts_ctx
, 1, &nullbyte
);
1752 /*********************************************************************
1753 * _vsprintf_p_l (MSVCRT.@)
1755 int CDECL
_vsprintf_p_l(char *buffer
, size_t length
, const char *format
,
1756 _locale_t locale
, __ms_va_list args
)
1758 return vsprintf_p_l_opt(buffer
, length
, format
, 0, locale
, args
);
1761 /*********************************************************************
1762 * _vsprintf_p (MSVCRT.@)
1764 int CDECL
_vsprintf_p(char *buffer
, size_t length
,
1765 const char *format
, __ms_va_list args
)
1767 return _vsprintf_p_l(buffer
, length
, format
, NULL
, args
);
1771 /*********************************************************************
1772 * __stdio_common_vsprintf_p (UCRTBASE.@)
1774 int CDECL
__stdio_common_vsprintf_p(unsigned __int64 options
, char *buffer
, size_t length
,
1775 const char *format
, _locale_t locale
, __ms_va_list args
)
1777 if (options
& ~UCRTBASE_PRINTF_MASK
)
1778 FIXME("options %s not handled\n", wine_dbgstr_longlong(options
));
1779 return vsprintf_p_l_opt(buffer
, length
, format
, options
& UCRTBASE_PRINTF_MASK
, locale
, args
);
1783 /*********************************************************************
1784 * _sprintf_p_l (MSVCRT.@)
1786 int WINAPIV
_sprintf_p_l(char *buffer
, size_t length
,
1787 const char *format
, _locale_t locale
, ...)
1789 __ms_va_list valist
;
1792 __ms_va_start(valist
, locale
);
1793 r
= _vsprintf_p_l(buffer
, length
, format
, locale
, valist
);
1794 __ms_va_end(valist
);
1799 /*********************************************************************
1800 * __swprintf_l (MSVCRT.@)
1802 int WINAPIV
__swprintf_l( wchar_t *str
, const wchar_t *format
,
1803 _locale_t locale
, ...)
1806 __ms_va_list valist
;
1807 __ms_va_start(valist
, locale
);
1808 retval
= _vswprintf_l(str
, format
, locale
, valist
);
1809 __ms_va_end(valist
);
1814 /*********************************************************************
1815 * _sprintf_p (MSVCR80.@)
1817 int WINAPIV
_sprintf_p(char *buffer
, size_t length
, const char *format
, ...)
1819 __ms_va_list valist
;
1822 __ms_va_start(valist
, format
);
1823 r
= _vsprintf_p_l(buffer
, length
, format
, NULL
, valist
);
1824 __ms_va_end(valist
);
1830 /*********************************************************************
1831 * _swprintf_p_l (MSVCRT.@)
1833 int WINAPIV
_swprintf_p_l(wchar_t *buffer
, size_t length
,
1834 const wchar_t *format
, _locale_t locale
, ...)
1836 __ms_va_list valist
;
1839 __ms_va_start(valist
, locale
);
1840 r
= vswprintf_p_l_opt(buffer
, length
, format
, 0, locale
, valist
);
1841 __ms_va_end(valist
);
1846 /*********************************************************************
1849 int CDECL
wcscmp(const wchar_t *str1
, const wchar_t *str2
)
1851 while (*str1
&& (*str1
== *str2
))
1864 /*********************************************************************
1865 * _wcscoll_l (MSVCRT.@)
1867 int CDECL
_wcscoll_l(const wchar_t* str1
, const wchar_t* str2
, _locale_t locale
)
1869 pthreadlocinfo locinfo
;
1872 locinfo
= get_locinfo();
1874 locinfo
= locale
->locinfo
;
1876 if(!locinfo
->lc_handle
[LC_COLLATE
])
1877 return wcscmp(str1
, str2
);
1878 return CompareStringW(locinfo
->lc_handle
[LC_COLLATE
], 0, str1
, -1, str2
, -1)-CSTR_EQUAL
;
1881 /*********************************************************************
1882 * wcscoll (MSVCRT.@)
1884 int CDECL
wcscoll( const wchar_t* str1
, const wchar_t* str2
)
1886 return _wcscoll_l(str1
, str2
, NULL
);
1889 /*********************************************************************
1890 * wcspbrk (MSVCRT.@)
1892 wchar_t* CDECL
wcspbrk( const wchar_t* str
, const wchar_t* accept
)
1898 for (p
= accept
; *p
; p
++) if (*p
== *str
) return (wchar_t*)str
;
1904 /*********************************************************************
1905 * wcstok_s (MSVCRT.@)
1907 wchar_t * CDECL
wcstok_s( wchar_t *str
, const wchar_t *delim
,
1908 wchar_t **next_token
)
1912 if (!MSVCRT_CHECK_PMT(delim
!= NULL
)) return NULL
;
1913 if (!MSVCRT_CHECK_PMT(next_token
!= NULL
)) return NULL
;
1914 if (!MSVCRT_CHECK_PMT(str
!= NULL
|| *next_token
!= NULL
)) return NULL
;
1916 if (!str
) str
= *next_token
;
1918 while (*str
&& wcschr( delim
, *str
)) str
++;
1919 if (!*str
) ret
= NULL
;
1923 while (*str
&& !wcschr( delim
, *str
)) str
++;
1924 if (*str
) *str
++ = 0;
1930 /*********************************************************************
1934 wchar_t * CDECL
wcstok( wchar_t *str
, const wchar_t *delim
, wchar_t **ctx
)
1937 ctx
= &msvcrt_get_thread_data()->wcstok_next
;
1938 return wcstok_s(str
, delim
, ctx
);
1941 wchar_t * CDECL
wcstok( wchar_t *str
, const wchar_t *delim
)
1943 return wcstok_s(str
, delim
, &msvcrt_get_thread_data()->wcstok_next
);
1947 /*********************************************************************
1948 * _wctomb_s_l (MSVCRT.@)
1950 int CDECL
_wctomb_s_l(int *len
, char *mbchar
, size_t size
,
1951 wchar_t wch
, _locale_t locale
)
1953 pthreadlocinfo locinfo
;
1958 if(!mbchar
&& size
>0) {
1967 if(!MSVCRT_CHECK_PMT(size
<= INT_MAX
))
1971 locinfo
= get_locinfo();
1973 locinfo
= locale
->locinfo
;
1975 if(!locinfo
->lc_codepage
) {
1977 if(mbchar
&& size
>0)
1978 memset(mbchar
, 0, size
);
1983 if(!MSVCRT_CHECK_PMT_ERR(size
>= 1, ERANGE
))
1992 perror
= (locinfo
->lc_codepage
!= CP_UTF8
? &error
: NULL
);
1993 mblen
= WideCharToMultiByte(locinfo
->lc_codepage
, 0, &wch
, 1, mbchar
, size
, NULL
, perror
);
1994 if(!mblen
|| error
) {
1995 if(!mblen
&& GetLastError()==ERROR_INSUFFICIENT_BUFFER
) {
1996 if(mbchar
&& size
>0)
1997 memset(mbchar
, 0, size
);
1999 MSVCRT_INVALID_PMT("insufficient buffer size", ERANGE
);
2012 /*********************************************************************
2013 * wctomb_s (MSVCRT.@)
2015 int CDECL
wctomb_s(int *len
, char *mbchar
, size_t size
, wchar_t wch
)
2017 return _wctomb_s_l(len
, mbchar
, size
, wch
, NULL
);
2020 /*********************************************************************
2021 * _wctomb_l (MSVCRT.@)
2023 int CDECL
_wctomb_l(char *dst
, wchar_t ch
, _locale_t locale
)
2027 _wctomb_s_l(&len
, dst
, dst
? MB_LEN_MAX
: 0, ch
, locale
);
2031 /*********************************************************************
2034 INT CDECL
wctomb( char *dst
, wchar_t ch
)
2036 return _wctomb_l(dst
, ch
, NULL
);
2039 /*********************************************************************
2042 INT CDECL
wctob( wint_t wchar
)
2047 UINT codepage
= get_locinfo()->lc_codepage
;
2049 perror
= (codepage
!= CP_UTF8
? &error
: NULL
);
2053 return (signed char)wchar
;
2056 } else if(WideCharToMultiByte( codepage
, 0, &wchar
, 1, &out
, 1, NULL
, perror
) && !error
)
2061 /*********************************************************************
2062 * wcrtomb_s (MSVCRT.@)
2064 INT CDECL
wcrtomb_s(size_t *len
, char *mbchar
,
2065 size_t size
, wchar_t wch
, mbstate_t *s
)
2070 ret
= wctomb_s(&ilen
, mbchar
, size
, wch
);
2071 if (len
) *len
= ilen
;
2075 /*********************************************************************
2076 * wcrtomb (MSVCRT.@)
2078 size_t CDECL
wcrtomb( char *dst
, wchar_t ch
, mbstate_t *s
)
2082 return wctomb(dst
, ch
);
2085 /*********************************************************************
2086 * _iswctype_l (MSVCRT.@)
2088 INT CDECL
_iswctype_l( wchar_t wc
, wctype_t type
, _locale_t locale
)
2092 if (wc
== WEOF
) return 0;
2093 if (wc
< 256) return MSVCRT__pwctype
[wc
] & type
;
2095 if (!GetStringTypeW(CT_CTYPE1
, &wc
, 1, &ct
))
2097 ERR("GetStringTypeW failed for %x\n", wc
);
2103 /*********************************************************************
2104 * iswctype (MSVCRT.@)
2106 INT CDECL
iswctype( wchar_t wc
, wctype_t type
)
2108 return _iswctype_l( wc
, type
, NULL
);
2111 /*********************************************************************
2112 * _iswalnum_l (MSVCRT.@)
2114 int CDECL
_iswalnum_l( wchar_t wc
, _locale_t locale
)
2116 return _iswctype_l( wc
, _ALPHA
| _DIGIT
, locale
);
2119 /*********************************************************************
2120 * iswalnum (MSVCRT.@)
2122 INT CDECL
iswalnum( wchar_t wc
)
2124 return _iswalnum_l( wc
, NULL
);
2127 /*********************************************************************
2128 * iswalpha_l (MSVCRT.@)
2130 INT CDECL
_iswalpha_l( wchar_t wc
, _locale_t locale
)
2132 return _iswctype_l( wc
, _ALPHA
, locale
);
2135 /*********************************************************************
2136 * iswalpha (MSVCRT.@)
2138 INT CDECL
iswalpha( wchar_t wc
)
2140 return _iswalpha_l( wc
, NULL
);
2143 /*********************************************************************
2144 * _iswcntrl_l (MSVCRT.@)
2146 int CDECL
_iswcntrl_l( wchar_t wc
, _locale_t locale
)
2148 return _iswctype_l( wc
, _CONTROL
, locale
);
2151 /*********************************************************************
2152 * iswcntrl (MSVCRT.@)
2154 INT CDECL
iswcntrl( wchar_t wc
)
2156 return _iswcntrl_l( wc
, NULL
);
2159 /*********************************************************************
2160 * _iswdigit_l (MSVCRT.@)
2162 INT CDECL
_iswdigit_l( wchar_t wc
, _locale_t locale
)
2164 return _iswctype_l( wc
, _DIGIT
, locale
);
2167 /*********************************************************************
2168 * iswdigit (MSVCRT.@)
2170 INT CDECL
iswdigit( wchar_t wc
)
2172 return _iswdigit_l( wc
, NULL
);
2175 /*********************************************************************
2176 * _iswgraph_l (MSVCRT.@)
2178 int CDECL
_iswgraph_l( wchar_t wc
, _locale_t locale
)
2180 return _iswctype_l( wc
, _ALPHA
| _DIGIT
| _PUNCT
, locale
);
2183 /*********************************************************************
2184 * iswgraph (MSVCRT.@)
2186 INT CDECL
iswgraph( wchar_t wc
)
2188 return _iswgraph_l( wc
, NULL
);
2191 /*********************************************************************
2192 * _iswlower_l (MSVCRT.@)
2194 int CDECL
_iswlower_l( wchar_t wc
, _locale_t locale
)
2196 return _iswctype_l( wc
, _LOWER
, locale
);
2199 /*********************************************************************
2200 * iswlower (MSVCRT.@)
2202 INT CDECL
iswlower( wchar_t wc
)
2204 return _iswlower_l( wc
, NULL
);
2207 /*********************************************************************
2208 * _iswprint_l (MSVCRT.@)
2210 int CDECL
_iswprint_l( wchar_t wc
, _locale_t locale
)
2212 return _iswctype_l( wc
, _ALPHA
| _BLANK
| _DIGIT
| _PUNCT
, locale
);
2215 /*********************************************************************
2216 * iswprint (MSVCRT.@)
2218 INT CDECL
iswprint( wchar_t wc
)
2220 return _iswprint_l( wc
, NULL
);
2223 /*********************************************************************
2224 * _iswpunct_l (MSVCRT.@)
2226 INT CDECL
_iswpunct_l( wchar_t wc
, _locale_t locale
)
2228 return _iswctype_l( wc
, _PUNCT
, locale
);
2231 /*********************************************************************
2232 * iswpunct (MSVCRT.@)
2234 INT CDECL
iswpunct( wchar_t wc
)
2236 return _iswpunct_l( wc
, NULL
);
2239 /*********************************************************************
2240 * _iswspace_l (MSVCRT.@)
2242 INT CDECL
_iswspace_l( wchar_t wc
, _locale_t locale
)
2244 return _iswctype_l( wc
, _SPACE
, locale
);
2247 /*********************************************************************
2248 * iswspace (MSVCRT.@)
2250 INT CDECL
iswspace( wchar_t wc
)
2252 return _iswspace_l( wc
, NULL
);
2255 /*********************************************************************
2256 * _iswupper_l (MSVCRT.@)
2258 int CDECL
_iswupper_l( wchar_t wc
, _locale_t locale
)
2260 return _iswctype_l( wc
, _UPPER
, locale
);
2263 /*********************************************************************
2264 * iswupper (MSVCRT.@)
2266 INT CDECL
iswupper( wchar_t wc
)
2268 return _iswupper_l( wc
, NULL
);
2271 /*********************************************************************
2272 * _iswxdigit_l (MSVCRT.@)
2274 int CDECL
_iswxdigit_l( wchar_t wc
, _locale_t locale
)
2276 return _iswctype_l( wc
, _HEX
, locale
);
2279 /*********************************************************************
2280 * iswxdigit (MSVCRT.@)
2282 INT CDECL
iswxdigit( wchar_t wc
)
2284 return _iswxdigit_l( wc
, NULL
);
2287 /*********************************************************************
2288 * _iswblank_l (MSVCRT.@)
2290 INT CDECL
_iswblank_l( wchar_t wc
, _locale_t locale
)
2292 return wc
== '\t' || _iswctype_l( wc
, _BLANK
, locale
);
2295 /*********************************************************************
2296 * iswblank (MSVCRT.@)
2298 INT CDECL
iswblank( wchar_t wc
)
2300 return wc
== '\t' || _iswctype_l( wc
, _BLANK
, NULL
);
2303 /*********************************************************************
2304 * wcscpy_s (MSVCRT.@)
2306 INT CDECL
wcscpy_s( wchar_t* wcDest
, size_t numElement
, const wchar_t *wcSrc
)
2310 if(!MSVCRT_CHECK_PMT(wcDest
)) return EINVAL
;
2311 if(!MSVCRT_CHECK_PMT(numElement
)) return EINVAL
;
2313 if(!MSVCRT_CHECK_PMT(wcSrc
))
2319 size
= wcslen(wcSrc
) + 1;
2321 if(!MSVCRT_CHECK_PMT_ERR(size
<= numElement
, ERANGE
))
2327 memmove( wcDest
, wcSrc
, size
*sizeof(WCHAR
) );
2332 /***********************************************************************
2335 wchar_t* __cdecl
wcscpy( wchar_t *dst
, const wchar_t *src
)
2338 while ((*p
++ = *src
++));
2342 /******************************************************************
2343 * wcsncpy (MSVCRT.@)
2345 wchar_t* __cdecl
wcsncpy( wchar_t* s1
, const wchar_t *s2
, size_t n
)
2350 if(!(s1
[i
] = s2
[i
])) break;
2356 /******************************************************************
2357 * wcsncpy_s (MSVCRT.@)
2359 INT CDECL
wcsncpy_s( wchar_t* wcDest
, size_t numElement
, const wchar_t *wcSrc
,
2363 BOOL truncate
= (count
== _TRUNCATE
);
2365 if(!wcDest
&& !numElement
&& !count
)
2368 if (!wcDest
|| !numElement
)
2374 return count
? EINVAL
: 0;
2377 while (numElement
&& count
&& *wcSrc
)
2383 if (!numElement
&& truncate
)
2388 else if (!numElement
)
2398 /******************************************************************
2399 * wcscat_s (MSVCRT.@)
2402 INT CDECL
wcscat_s(wchar_t* dst
, size_t elem
, const wchar_t* src
)
2406 if (!dst
|| elem
== 0) return EINVAL
;
2413 /* seek to end of dst string (or elem if no end of string is found */
2414 while (ptr
< dst
+ elem
&& *ptr
!= '\0') ptr
++;
2415 while (ptr
< dst
+ elem
)
2417 if ((*ptr
++ = *src
++) == '\0') return 0;
2419 /* not enough space */
2424 /***********************************************************************
2427 wchar_t* __cdecl
wcscat( wchar_t *dst
, const wchar_t *src
)
2429 wcscpy( dst
+ wcslen(dst
), src
);
2433 /*********************************************************************
2434 * wcsncat_s (MSVCRT.@)
2437 INT CDECL
wcsncat_s(wchar_t *dst
, size_t elem
,
2438 const wchar_t *src
, size_t count
)
2444 if (!MSVCRT_CHECK_PMT(dst
!= NULL
)) return EINVAL
;
2445 if (!MSVCRT_CHECK_PMT(elem
> 0)) return EINVAL
;
2446 if (!MSVCRT_CHECK_PMT(src
!= NULL
|| count
== 0)) return EINVAL
;
2451 for (dststart
= 0; dststart
< elem
; dststart
++)
2453 if (dst
[dststart
] == '\0')
2456 if (dststart
== elem
)
2458 MSVCRT_INVALID_PMT("dst[elem] is not NULL terminated\n", EINVAL
);
2462 if (count
== _TRUNCATE
)
2464 srclen
= wcslen(src
);
2465 if (srclen
>= (elem
- dststart
))
2467 srclen
= elem
- dststart
- 1;
2472 srclen
= min(wcslen(src
), count
);
2473 if (srclen
< (elem
- dststart
))
2475 memcpy(&dst
[dststart
], src
, srclen
*sizeof(wchar_t));
2476 dst
[dststart
+srclen
] = '\0';
2479 MSVCRT_INVALID_PMT("dst[elem] is too small", ERANGE
);
2484 /*********************************************************************
2485 * wctoint (INTERNAL)
2487 static int wctoint(WCHAR c
, int base
)
2490 if ('0' <= c
&& c
<= '9')
2492 else if ('A' <= c
&& c
<= 'Z')
2494 else if ('a' <= c
&& c
<= 'z')
2497 /* NOTE: wine_fold_string(MAP_FOLDDIGITS) supports too many things. */
2498 /* Unicode points that contain digits 0-9; keep this sorted! */
2499 static const WCHAR zeros
[] = {
2500 0x660, 0x6f0, 0x966, 0x9e6, 0xa66, 0xae6, 0xb66, 0xc66, 0xce6,
2501 0xd66, 0xe50, 0xed0, 0xf20, 0x1040, 0x17e0, 0x1810, 0xff10
2504 for (i
= 0; i
< ARRAY_SIZE(zeros
) && c
>= zeros
[i
]; ++i
) {
2505 if (zeros
[i
] <= c
&& c
<= zeros
[i
] + 9) {
2511 return v
< base
? v
: -1;
2514 /*********************************************************************
2515 * _wcstoi64_l (MSVCRT.@)
2517 __int64 CDECL
_wcstoi64_l(const wchar_t *nptr
,
2518 wchar_t **endptr
, int base
, _locale_t locale
)
2520 BOOL negative
= FALSE
, empty
= TRUE
;
2523 TRACE("(%s %p %d %p)\n", debugstr_w(nptr
), endptr
, base
, locale
);
2525 if (!MSVCRT_CHECK_PMT(nptr
!= NULL
)) return 0;
2526 if (!MSVCRT_CHECK_PMT(base
== 0 || base
>= 2)) return 0;
2527 if (!MSVCRT_CHECK_PMT(base
<= 36)) return 0;
2530 *endptr
= (wchar_t*)nptr
;
2532 while(_iswspace_l(*nptr
, locale
)) nptr
++;
2537 } else if(*nptr
== '+')
2540 if((base
==0 || base
==16) && wctoint(*nptr
, 1)==0 && (nptr
[1]=='x' || nptr
[1]=='X')) {
2546 if(wctoint(*nptr
, 1)==0)
2553 int v
= wctoint(*nptr
, base
);
2563 if(!negative
&& (ret
>I64_MAX
/base
|| ret
*base
>I64_MAX
-v
)) {
2566 } else if(negative
&& (ret
<I64_MIN
/base
|| ret
*base
<I64_MIN
-v
)) {
2573 if(endptr
&& !empty
)
2574 *endptr
= (wchar_t*)nptr
;
2579 /*********************************************************************
2580 * _wcstoi64 (MSVCRT.@)
2582 __int64 CDECL
_wcstoi64(const wchar_t *nptr
,
2583 wchar_t **endptr
, int base
)
2585 return _wcstoi64_l(nptr
, endptr
, base
, NULL
);
2588 /*********************************************************************
2589 * _wcstol_l (MSVCRT.@)
2591 __msvcrt_long CDECL
_wcstol_l(const wchar_t *s
,
2592 wchar_t **end
, int base
, _locale_t locale
)
2594 __int64 ret
= _wcstoi64_l(s
, end
, base
, locale
);
2596 if(ret
> LONG_MAX
) {
2599 }else if(ret
< LONG_MIN
) {
2606 /*********************************************************************
2609 __msvcrt_long CDECL
wcstol(const wchar_t *s
,
2610 wchar_t **end
, int base
)
2612 return _wcstol_l(s
, end
, base
, NULL
);
2615 /*********************************************************************
2616 * _wtoi_l (MSVCRT.@)
2618 int __cdecl
_wtoi_l(const wchar_t *str
, _locale_t locale
)
2620 __int64 ret
= _wcstoi64_l(str
, NULL
, 10, locale
);
2625 } else if(ret
< INT_MIN
) {
2632 /*********************************************************************
2635 int __cdecl
_wtoi(const wchar_t *str
)
2637 return _wtoi_l(str
, NULL
);
2640 /*********************************************************************
2641 * _wtol_l (MSVCRT.@)
2643 __msvcrt_long __cdecl
_wtol_l(const wchar_t *str
, _locale_t locale
)
2645 __int64 ret
= _wcstoi64_l(str
, NULL
, 10, locale
);
2647 if(ret
> LONG_MAX
) {
2650 } else if(ret
< LONG_MIN
) {
2657 /*********************************************************************
2660 __msvcrt_long __cdecl
_wtol(const wchar_t *str
)
2662 return _wtol_l(str
, NULL
);
2667 /*********************************************************************
2668 * _wtoll_l (MSVCR120.@)
2670 __int64 __cdecl
_wtoll_l(const wchar_t *str
, _locale_t locale
)
2672 return _wcstoi64_l(str
, NULL
, 10, locale
);
2675 /*********************************************************************
2676 * _wtoll (MSVCR120.@)
2678 __int64 __cdecl
_wtoll(const wchar_t *str
)
2680 return _wtoll_l(str
, NULL
);
2683 #endif /* _MSVCR_VER>=120 */
2685 /*********************************************************************
2686 * _wcstoui64_l (MSVCRT.@)
2688 unsigned __int64 CDECL
_wcstoui64_l(const wchar_t *nptr
,
2689 wchar_t **endptr
, int base
, _locale_t locale
)
2691 BOOL negative
= FALSE
, empty
= TRUE
;
2692 unsigned __int64 ret
= 0;
2694 TRACE("(%s %p %d %p)\n", debugstr_w(nptr
), endptr
, base
, locale
);
2696 if (!MSVCRT_CHECK_PMT(nptr
!= NULL
)) return 0;
2697 if (!MSVCRT_CHECK_PMT(base
== 0 || base
>= 2)) return 0;
2698 if (!MSVCRT_CHECK_PMT(base
<= 36)) return 0;
2701 *endptr
= (wchar_t*)nptr
;
2703 while(_iswspace_l(*nptr
, locale
)) nptr
++;
2708 } else if(*nptr
== '+')
2711 if((base
==0 || base
==16) && wctoint(*nptr
, 1)==0 && (nptr
[1]=='x' || nptr
[1]=='X')) {
2717 if(wctoint(*nptr
, 1)==0)
2724 int v
= wctoint(*nptr
, base
);
2731 if(ret
>UI64_MAX
/base
|| ret
*base
>UI64_MAX
-v
) {
2738 if(endptr
&& !empty
)
2739 *endptr
= (wchar_t*)nptr
;
2741 return negative
? -ret
: ret
;
2744 /*********************************************************************
2745 * _wcstoui64 (MSVCRT.@)
2747 unsigned __int64 CDECL
_wcstoui64(const wchar_t *nptr
,
2748 wchar_t **endptr
, int base
)
2750 return _wcstoui64_l(nptr
, endptr
, base
, NULL
);
2753 /*********************************************************************
2754 * _wcstoul_l (MSVCRT.@)
2756 __msvcrt_ulong __cdecl
_wcstoul_l(const wchar_t *s
,
2757 wchar_t **end
, int base
, _locale_t locale
)
2759 __int64 ret
= _wcstoi64_l(s
, end
, base
, locale
);
2761 if(ret
> ULONG_MAX
) {
2764 }else if(ret
< -(__int64
)ULONG_MAX
) {
2771 /*********************************************************************
2772 * wcstoul (MSVCRT.@)
2774 __msvcrt_ulong __cdecl
wcstoul(const wchar_t *s
, wchar_t **end
, int base
)
2776 return _wcstoul_l(s
, end
, base
, NULL
);
2779 /******************************************************************
2780 * wcsnlen (MSVCRT.@)
2782 size_t CDECL
wcsnlen(const wchar_t *s
, size_t maxlen
)
2786 for (i
= 0; i
< maxlen
; i
++)
2791 /*********************************************************************
2792 * _towupper_l (MSVCRT.@)
2794 wint_t CDECL
_towupper_l(wint_t c
, _locale_t locale
)
2796 pthreadlocinfo locinfo
;
2800 locinfo
= get_locinfo();
2802 locinfo
= locale
->locinfo
;
2804 if(!locinfo
->lc_handle
[LC_CTYPE
]) {
2805 if(c
>= 'a' && c
<= 'z')
2806 return c
+ 'A' - 'a';
2810 if(!LCMapStringW(locinfo
->lc_handle
[LC_CTYPE
], LCMAP_UPPERCASE
, &c
, 1, &ret
, 1))
2815 /*********************************************************************
2816 * towupper (MSVCRT.@)
2818 wint_t CDECL
towupper(wint_t c
)
2820 return _towupper_l(c
, NULL
);
2823 /*********************************************************************
2826 wchar_t* CDECL
wcschr(const wchar_t *str
, wchar_t ch
)
2828 do { if (*str
== ch
) return (WCHAR
*)(ULONG_PTR
)str
; } while (*str
++);
2832 /*********************************************************************
2833 * wcsrchr (MSVCRT.@)
2835 wchar_t* CDECL
wcsrchr(const wchar_t *str
, wchar_t ch
)
2838 do { if (*str
== ch
) ret
= (WCHAR
*)(ULONG_PTR
)str
; } while (*str
++);
2842 /***********************************************************************
2845 size_t CDECL
wcslen(const wchar_t *str
)
2847 const wchar_t *s
= str
;
2852 /*********************************************************************
2855 wchar_t* CDECL
wcsstr(const wchar_t *str
, const wchar_t *sub
)
2859 const wchar_t *p1
= str
, *p2
= sub
;
2860 while(*p1
&& *p2
&& *p1
== *p2
)
2866 return (wchar_t*)str
;
2872 /*********************************************************************
2873 * _wtoi64_l (MSVCRT.@)
2875 __int64 CDECL
_wtoi64_l(const wchar_t *str
, _locale_t locale
)
2877 ULONGLONG RunningTotal
= 0;
2878 BOOL bMinus
= FALSE
;
2880 while (_iswspace_l(*str
, locale
)) {
2886 } else if (*str
== '-') {
2891 while (*str
>= '0' && *str
<= '9') {
2892 RunningTotal
= RunningTotal
* 10 + *str
- '0';
2896 return bMinus
? -RunningTotal
: RunningTotal
;
2899 /*********************************************************************
2900 * _wtoi64 (MSVCRT.@)
2902 __int64 CDECL
_wtoi64(const wchar_t *str
)
2904 return _wtoi64_l(str
, NULL
);
2907 /*********************************************************************
2908 * _wcsxfrm_l (MSVCRT.@)
2910 size_t CDECL
_wcsxfrm_l(wchar_t *dest
, const wchar_t *src
,
2911 size_t len
, _locale_t locale
)
2913 pthreadlocinfo locinfo
;
2916 if(!MSVCRT_CHECK_PMT(src
)) return INT_MAX
;
2917 if(!MSVCRT_CHECK_PMT(dest
|| !len
)) return INT_MAX
;
2920 FIXME("len > INT_MAX not supported\n");
2925 locinfo
= get_locinfo();
2927 locinfo
= locale
->locinfo
;
2929 if(!locinfo
->lc_handle
[LC_COLLATE
]) {
2930 wcsncpy(dest
, src
, len
);
2934 ret
= LCMapStringW(locinfo
->lc_handle
[LC_COLLATE
],
2935 LCMAP_SORTKEY
, src
, -1, NULL
, 0);
2937 if(len
) dest
[0] = 0;
2941 if(!len
) return ret
-1;
2949 ret
= LCMapStringW(locinfo
->lc_handle
[LC_COLLATE
],
2950 LCMAP_SORTKEY
, src
, -1, dest
, len
) - 1;
2951 for(i
=ret
; i
>=0; i
--)
2952 dest
[i
] = ((unsigned char*)dest
)[i
];
2956 /*********************************************************************
2957 * wcsxfrm (MSVCRT.@)
2959 size_t CDECL
wcsxfrm(wchar_t *dest
, const wchar_t *src
, size_t len
)
2961 return _wcsxfrm_l(dest
, src
, len
, NULL
);