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 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
)
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*);
830 ERR("Incorrect type\n");
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
;
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
};
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
);
865 static int puts_clbk_str_c99_a(void *ctx
, int len
, const char *str
)
867 struct _str_ctx_a
*out
= ctx
;
873 memmove(out
->buf
, str
, out
->len
);
874 out
->buf
+= out
->len
;
879 memmove(out
->buf
, str
, 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
};
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
);
903 if(options
& _CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION
)
904 return ret
>len
? -1 : ret
;
906 if(len
) str
[len
-1] = 0;
907 if(options
& _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR
)
909 return len
> 0 ? -2 : -1;
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
};
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
);
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
, ...)
949 __ms_va_start(valist
, locale
);
950 retval
= _vsnprintf_l(str
, INT_MAX
, format
, locale
, valist
);
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
;
963 if(sizeOfBuffer
<count
+1 || count
==-1)
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
);
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
;
995 if(count
!=-1 && len
>count
+1)
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));
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
, ...)
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
);
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
);
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
};
1170 memset(args_ctx
, 0, sizeof(args_ctx
));
1172 ret
= create_positional_ctx_a(args_ctx
, format
, args
);
1174 _invalid_parameter(NULL
, NULL
, NULL
, 0, 0);
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
);
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
);
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
, ...)
1204 __ms_va_list valist
;
1205 __ms_va_start(valist
, format
);
1206 retval
= vsnprintf(str
, len
, format
, valist
);
1207 __ms_va_end(valist
);
1211 /*********************************************************************
1212 * _snprintf_l (MSVCRT.@)
1214 int WINAPIV
_snprintf_l(char *str
, size_t count
, const char *format
,
1215 _locale_t locale
, ...)
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
);
1225 /*********************************************************************
1226 * _snprintf_c_l (MSVCRT.@)
1228 int WINAPIV
_snprintf_c_l(char *str
, size_t count
, const char *format
,
1229 _locale_t locale
, ...)
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
);
1239 /*********************************************************************
1240 * _snprintf_c (MSVCRT.@)
1242 int WINAPIV
_snprintf_c(char *str
, size_t count
, const char *format
, ...)
1245 __ms_va_list valist
;
1246 __ms_va_start(valist
, format
);
1247 retval
= _vsnprintf_c(str
, count
, format
, valist
);
1248 __ms_va_end(valist
);
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
, ...)
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
);
1266 /*********************************************************************
1267 * _snprintf_s (MSVCRT.@)
1269 int WINAPIV
_snprintf_s(char *str
, size_t len
, size_t count
,
1270 const char *format
, ...)
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
);
1280 /*********************************************************************
1281 * _scprintf (MSVCRT.@)
1283 int WINAPIV
_scprintf(const char *format
, ...)
1286 __ms_va_list valist
;
1287 __ms_va_start(valist
, format
);
1288 retval
= _vscprintf(format
, valist
);
1289 __ms_va_end(valist
);
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
};
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
"");
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
};
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
"");
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
};
1348 memset(args_ctx
, 0, sizeof(args_ctx
));
1350 ret
= create_positional_ctx_w(args_ctx
, format
, args
);
1352 _invalid_parameter(NULL
, NULL
, NULL
, 0, 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
);
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
"");
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
);
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
);
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
);
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
, ...)
1427 __ms_va_list valist
;
1428 __ms_va_start(valist
, format
);
1429 retval
= _vsnwprintf(str
, len
, format
, valist
);
1430 __ms_va_end(valist
);
1434 /*********************************************************************
1435 * _snwprintf_l (MSVCRT.@)
1437 int WINAPIV
_snwprintf_l( wchar_t *str
, size_t len
, const wchar_t *format
,
1438 _locale_t locale
, ...)
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
);
1448 /*********************************************************************
1449 * _snwprintf_s (MSVCRT.@)
1451 int WINAPIV
_snwprintf_s( wchar_t *str
, size_t len
, size_t count
,
1452 const wchar_t *format
, ...)
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
);
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
, ... )
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
);
1478 static int puts_clbk_str_c99_w(void *ctx
, int len
, const wchar_t *str
)
1480 struct _str_ctx_w
*out
= ctx
;
1485 if(out
->len
< len
) {
1486 memcpy(out
->buf
, str
, out
->len
*sizeof(wchar_t));
1487 out
->buf
+= out
->len
;
1492 memcpy(out
->buf
, str
, len
*sizeof(wchar_t));
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
};
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
"");
1516 if(options
& _CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION
)
1517 return ret
>len
? -1 : ret
;
1519 if(len
) str
[len
-1] = 0;
1520 if(options
& _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR
)
1522 return len
> 0 ? -2 : -1;
1527 #endif /* _MSVCR_VER>=140 */
1529 /*********************************************************************
1530 * sprintf (MSVCRT.@)
1532 int WINAPIV
sprintf( char *str
, const char *format
, ... )
1537 __ms_va_start( ap
, format
);
1538 r
= vsnprintf( str
, INT_MAX
, format
, ap
);
1543 /*********************************************************************
1544 * sprintf_s (MSVCRT.@)
1546 int WINAPIV
sprintf_s( char *str
, size_t num
, const char *format
, ... )
1551 __ms_va_start( ap
, format
);
1552 r
= vsnprintf( str
, num
, format
, ap
);
1557 /*********************************************************************
1558 * _scwprintf (MSVCRT.@)
1560 int WINAPIV
_scwprintf( const wchar_t *format
, ... )
1565 __ms_va_start( ap
, format
);
1566 r
= _vsnwprintf( NULL
, INT_MAX
, format
, ap
);
1571 /*********************************************************************
1572 * swprintf (MSVCRT.@)
1574 int WINAPIV
_swprintf( wchar_t *str
, const wchar_t *format
, ... )
1579 __ms_va_start( ap
, format
);
1580 r
= _vsnwprintf( str
, INT_MAX
, format
, ap
);
1585 /*********************************************************************
1586 * swprintf_s (MSVCRT.@)
1588 int WINAPIV
swprintf_s(wchar_t *str
, size_t numberOfElements
,
1589 const wchar_t *format
, ... )
1594 __ms_va_start(ap
, format
);
1595 r
= _vsnwprintf_s(str
, numberOfElements
, INT_MAX
, format
, ap
);
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
, ... )
1610 __ms_va_start(ap
, locale
);
1611 r
= _vsnwprintf_s_l(str
, numberOfElements
, INT_MAX
, format
, locale
, ap
);
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
, ... )
1626 __ms_va_start(ap
, locale
);
1627 r
= _vswprintf_c_l(str
, len
, format
, locale
, ap
);
1633 /*********************************************************************
1634 * _swprintf_c (MSVCRT.@)
1636 int WINAPIV
_swprintf_c(wchar_t *str
, size_t len
,
1637 const wchar_t *format
, ... )
1642 __ms_va_start(ap
, format
);
1643 r
= _vswprintf_c(str
, len
, format
, ap
);
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
);
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
);
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
};
1727 memset(args_ctx
, 0, sizeof(args_ctx
));
1729 ret
= create_positional_ctx_a(args_ctx
, format
, args
);
1731 _invalid_parameter(NULL
, NULL
, NULL
, 0, 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
);
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
);
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
);
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
);
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
;
1786 __ms_va_start(valist
, locale
);
1787 r
= _vsprintf_p_l(buffer
, length
, format
, locale
, valist
);
1788 __ms_va_end(valist
);
1793 /*********************************************************************
1794 * __swprintf_l (MSVCRT.@)
1796 int WINAPIV
__swprintf_l( wchar_t *str
, const wchar_t *format
,
1797 _locale_t locale
, ...)
1800 __ms_va_list valist
;
1801 __ms_va_start(valist
, locale
);
1802 retval
= _vswprintf_l(str
, format
, locale
, valist
);
1803 __ms_va_end(valist
);
1808 /*********************************************************************
1809 * _sprintf_p (MSVCR80.@)
1811 int WINAPIV
_sprintf_p(char *buffer
, size_t length
, const char *format
, ...)
1813 __ms_va_list valist
;
1816 __ms_va_start(valist
, format
);
1817 r
= _vsprintf_p_l(buffer
, length
, format
, NULL
, valist
);
1818 __ms_va_end(valist
);
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
;
1833 __ms_va_start(valist
, locale
);
1834 r
= vswprintf_p_l_opt(buffer
, length
, format
, 0, locale
, valist
);
1835 __ms_va_end(valist
);
1840 /*********************************************************************
1843 int CDECL
wcscmp(const wchar_t *str1
, const wchar_t *str2
)
1845 while (*str1
&& (*str1
== *str2
))
1858 /*********************************************************************
1859 * _wcscoll_l (MSVCRT.@)
1861 int CDECL
_wcscoll_l(const wchar_t* str1
, const wchar_t* str2
, _locale_t locale
)
1863 pthreadlocinfo locinfo
;
1866 locinfo
= get_locinfo();
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
)
1892 for (p
= accept
; *p
; p
++) if (*p
== *str
) return (wchar_t*)str
;
1898 /*********************************************************************
1899 * wcstok_s (MSVCRT.@)
1901 wchar_t * CDECL
wcstok_s( wchar_t *str
, const wchar_t *delim
,
1902 wchar_t **next_token
)
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
;
1915 while (*str
&& !wcschr( delim
, *str
)) str
++;
1916 if (*str
) *str
++ = 0;
1921 /*********************************************************************
1925 wchar_t * CDECL
wcstok( wchar_t *str
, const wchar_t *delim
, wchar_t **ctx
)
1928 ctx
= &msvcrt_get_thread_data()->wcstok_next
;
1929 return wcstok_s(str
, delim
, ctx
);
1932 wchar_t * CDECL
wcstok( wchar_t *str
, const wchar_t *delim
)
1934 return wcstok_s(str
, delim
, &msvcrt_get_thread_data()->wcstok_next
);
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
;
1949 if(!mbchar
&& size
>0) {
1958 if(!MSVCRT_CHECK_PMT(size
<= INT_MAX
))
1962 locinfo
= get_locinfo();
1964 locinfo
= locale
->locinfo
;
1966 if(!locinfo
->lc_codepage
) {
1968 if(mbchar
&& size
>0)
1969 memset(mbchar
, 0, size
);
1974 if(!MSVCRT_CHECK_PMT_ERR(size
>= 1, ERANGE
))
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
);
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
)
2018 _wctomb_s_l(&len
, dst
, dst
? MB_LEN_MAX
: 0, ch
, locale
);
2022 /*********************************************************************
2025 INT CDECL
wctomb( char *dst
, wchar_t ch
)
2027 return _wctomb_l(dst
, ch
, NULL
);
2030 /*********************************************************************
2033 INT CDECL
wctob( wint_t wchar
)
2038 UINT codepage
= get_locinfo()->lc_codepage
;
2040 perror
= (codepage
!= CP_UTF8
? &error
: NULL
);
2044 return (signed char)wchar
;
2047 } else if(WideCharToMultiByte( codepage
, 0, &wchar
, 1, &out
, 1, NULL
, perror
) && !error
)
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
)
2061 ret
= wctomb_s(&ilen
, mbchar
, size
, wch
);
2062 if (len
) *len
= ilen
;
2066 /*********************************************************************
2067 * wcrtomb (MSVCRT.@)
2069 size_t CDECL
wcrtomb( char *dst
, wchar_t ch
, mbstate_t *s
)
2073 return wctomb(dst
, ch
);
2076 /*********************************************************************
2077 * _iswctype_l (MSVCRT.@)
2079 INT CDECL
_iswctype_l( wchar_t wc
, wctype_t type
, _locale_t locale
)
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
);
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
)
2301 if(!MSVCRT_CHECK_PMT(wcDest
)) return EINVAL
;
2302 if(!MSVCRT_CHECK_PMT(numElement
)) return EINVAL
;
2304 if(!MSVCRT_CHECK_PMT(wcSrc
))
2310 size
= wcslen(wcSrc
) + 1;
2312 if(!MSVCRT_CHECK_PMT_ERR(size
<= numElement
, ERANGE
))
2318 memmove( wcDest
, wcSrc
, size
*sizeof(WCHAR
) );
2323 /***********************************************************************
2326 wchar_t* __cdecl
wcscpy( wchar_t *dst
, const wchar_t *src
)
2329 while ((*p
++ = *src
++));
2333 /******************************************************************
2334 * wcsncpy (MSVCRT.@)
2336 wchar_t* __cdecl
wcsncpy( wchar_t* s1
, const wchar_t *s2
, size_t n
)
2341 if(!(s1
[i
] = s2
[i
])) break;
2347 /******************************************************************
2348 * wcsncpy_s (MSVCRT.@)
2350 INT CDECL
wcsncpy_s( wchar_t* wcDest
, size_t numElement
, const wchar_t *wcSrc
,
2354 BOOL truncate
= (count
== _TRUNCATE
);
2356 if(!wcDest
&& !numElement
&& !count
)
2359 if (!wcDest
|| !numElement
)
2365 return count
? EINVAL
: 0;
2368 while (numElement
&& count
&& *wcSrc
)
2374 if (!numElement
&& truncate
)
2379 else if (!numElement
)
2389 /******************************************************************
2390 * wcscat_s (MSVCRT.@)
2393 INT CDECL
wcscat_s(wchar_t* dst
, size_t elem
, const wchar_t* src
)
2397 if (!dst
|| elem
== 0) 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 */
2415 /***********************************************************************
2418 wchar_t* __cdecl
wcscat( wchar_t *dst
, const wchar_t *src
)
2420 wcscpy( dst
+ wcslen(dst
), src
);
2424 /*********************************************************************
2425 * wcsncat_s (MSVCRT.@)
2428 INT CDECL
wcsncat_s(wchar_t *dst
, size_t elem
,
2429 const wchar_t *src
, size_t count
)
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
;
2442 for (dststart
= 0; dststart
< elem
; dststart
++)
2444 if (dst
[dststart
] == '\0')
2447 if (dststart
== elem
)
2449 MSVCRT_INVALID_PMT("dst[elem] is not NULL terminated\n", EINVAL
);
2453 if (count
== _TRUNCATE
)
2455 srclen
= wcslen(src
);
2456 if (srclen
>= (elem
- dststart
))
2458 srclen
= elem
- dststart
- 1;
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';
2470 MSVCRT_INVALID_PMT("dst[elem] is too small", ERANGE
);
2475 /*********************************************************************
2476 * wctoint (INTERNAL)
2478 static int wctoint(WCHAR c
, int base
)
2481 if ('0' <= c
&& c
<= '9')
2483 else if ('A' <= c
&& c
<= 'Z')
2485 else if ('a' <= c
&& c
<= 'z')
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
2495 for (i
= 0; i
< ARRAY_SIZE(zeros
) && c
>= zeros
[i
]; ++i
) {
2496 if (zeros
[i
] <= c
&& c
<= zeros
[i
] + 9) {
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
;
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;
2521 *endptr
= (wchar_t*)nptr
;
2523 while(_iswspace_l(*nptr
, locale
)) nptr
++;
2528 } else if(*nptr
== '+')
2531 if((base
==0 || base
==16) && wctoint(*nptr
, 1)==0 && (nptr
[1]=='x' || nptr
[1]=='X')) {
2537 if(wctoint(*nptr
, 1)==0)
2544 int v
= wctoint(*nptr
, base
);
2554 if(!negative
&& (ret
>I64_MAX
/base
|| ret
*base
>I64_MAX
-v
)) {
2557 } else if(negative
&& (ret
<I64_MIN
/base
|| ret
*base
<I64_MIN
-v
)) {
2564 if(endptr
&& !empty
)
2565 *endptr
= (wchar_t*)nptr
;
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
) {
2590 }else if(ret
< LONG_MIN
) {
2597 /*********************************************************************
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
);
2616 } else if(ret
< INT_MIN
) {
2623 /*********************************************************************
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
) {
2641 } else if(ret
< LONG_MIN
) {
2648 /*********************************************************************
2651 __msvcrt_long __cdecl
_wtol(const wchar_t *str
)
2653 return _wtol_l(str
, NULL
);
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;
2692 *endptr
= (wchar_t*)nptr
;
2694 while(_iswspace_l(*nptr
, locale
)) nptr
++;
2699 } else if(*nptr
== '+')
2702 if((base
==0 || base
==16) && wctoint(*nptr
, 1)==0 && (nptr
[1]=='x' || nptr
[1]=='X')) {
2708 if(wctoint(*nptr
, 1)==0)
2715 int v
= wctoint(*nptr
, base
);
2722 if(ret
>UI64_MAX
/base
|| ret
*base
>UI64_MAX
-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
) {
2755 }else if(ret
< -(__int64
)ULONG_MAX
) {
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
)
2777 for (i
= 0; i
< maxlen
; i
++)
2782 /*********************************************************************
2783 * _towupper_l (MSVCRT.@)
2785 wint_t CDECL
_towupper_l(wint_t c
, _locale_t locale
)
2787 pthreadlocinfo locinfo
;
2791 locinfo
= get_locinfo();
2793 locinfo
= locale
->locinfo
;
2795 if(!locinfo
->lc_handle
[LC_CTYPE
]) {
2796 if(c
>= 'a' && c
<= 'z')
2797 return c
+ 'A' - 'a';
2801 if(!LCMapStringW(locinfo
->lc_handle
[LC_CTYPE
], LCMAP_UPPERCASE
, &c
, 1, &ret
, 1))
2806 /*********************************************************************
2807 * towupper (MSVCRT.@)
2809 wint_t CDECL
towupper(wint_t c
)
2811 return _towupper_l(c
, NULL
);
2814 /*********************************************************************
2817 wchar_t* CDECL
wcschr(const wchar_t *str
, wchar_t ch
)
2819 do { if (*str
== ch
) return (WCHAR
*)(ULONG_PTR
)str
; } while (*str
++);
2823 /*********************************************************************
2824 * wcsrchr (MSVCRT.@)
2826 wchar_t* CDECL
wcsrchr(const wchar_t *str
, wchar_t ch
)
2829 do { if (*str
== ch
) ret
= (WCHAR
*)(ULONG_PTR
)str
; } while (*str
++);
2833 /***********************************************************************
2836 size_t CDECL
wcslen(const wchar_t *str
)
2838 const wchar_t *s
= str
;
2843 /*********************************************************************
2846 wchar_t* CDECL
wcsstr(const wchar_t *str
, const wchar_t *sub
)
2850 const wchar_t *p1
= str
, *p2
= sub
;
2851 while(*p1
&& *p2
&& *p1
== *p2
)
2857 return (wchar_t*)str
;
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
)) {
2877 } else if (*str
== '-') {
2882 while (*str
>= '0' && *str
<= '9') {
2883 RunningTotal
= RunningTotal
* 10 + *str
- '0';
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
;
2907 if(!MSVCRT_CHECK_PMT(src
)) return INT_MAX
;
2908 if(!MSVCRT_CHECK_PMT(dest
|| !len
)) return INT_MAX
;
2911 FIXME("len > INT_MAX not supported\n");
2916 locinfo
= get_locinfo();
2918 locinfo
= locale
->locinfo
;
2920 if(!locinfo
->lc_handle
[LC_COLLATE
]) {
2921 wcsncpy(dest
, src
, len
);
2925 ret
= LCMapStringW(locinfo
->lc_handle
[LC_COLLATE
],
2926 LCMAP_SORTKEY
, src
, -1, NULL
, 0);
2928 if(len
) dest
[0] = 0;
2932 if(!len
) 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
];
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
);