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 size_t __cdecl
wcscspn(const wchar_t *str
, const wchar_t *reject
)
497 for (ptr
= str
; *ptr
; ptr
++) if (wcschr( reject
, *ptr
)) break;
501 /*********************************************************************
504 size_t __cdecl
wcsspn(const wchar_t *str
, const wchar_t *accept
)
507 for (ptr
= str
; *ptr
; ptr
++) if (!wcschr( accept
, *ptr
)) break;
511 /*********************************************************************
514 int CDECL
wcsncmp(const wchar_t *str1
, const wchar_t *str2
, size_t n
)
518 while(--n
&& *str1
&& (*str1
== *str2
))
523 return *str1
- *str2
;
526 /*********************************************************************
527 * _wcsncoll_l (MSVCRT.@)
529 int CDECL
_wcsncoll_l(const wchar_t* str1
, const wchar_t* str2
,
530 size_t count
, _locale_t locale
)
532 pthreadlocinfo locinfo
;
535 locinfo
= get_locinfo();
537 locinfo
= locale
->locinfo
;
539 if(!locinfo
->lc_handle
[LC_COLLATE
])
540 return wcsncmp(str1
, str2
, count
);
541 return CompareStringW(locinfo
->lc_handle
[LC_COLLATE
], 0,
542 str1
, wcsnlen(str1
, count
),
543 str2
, wcsnlen(str2
, count
))-CSTR_EQUAL
;
546 /*********************************************************************
547 * _wcsncoll (MSVCRT.@)
549 int CDECL
_wcsncoll(const wchar_t* str1
, const wchar_t* str2
, size_t count
)
551 return _wcsncoll_l(str1
, str2
, count
, NULL
);
554 static wchar_t strtod_wstr_get(void *ctx
)
556 const wchar_t **p
= ctx
;
557 if (!**p
) return WEOF
;
561 static void strtod_wstr_unget(void *ctx
)
563 const wchar_t **p
= ctx
;
567 /*********************************************************************
568 * _wcstod_l (MSVCRT.@)
570 double CDECL
_wcstod_l(const wchar_t* str
, wchar_t** end
,
573 pthreadlocinfo locinfo
;
574 const wchar_t *beg
, *p
;
579 if (!MSVCRT_CHECK_PMT(str
!= NULL
)) {
580 if (end
) *end
= NULL
;
585 locinfo
= get_locinfo();
587 locinfo
= locale
->locinfo
;
590 while(_iswspace_l(*p
, locale
))
594 fp
= fpnum_parse(strtod_wstr_get
, strtod_wstr_unget
, &p
, locinfo
, FALSE
);
595 if (end
) *end
= (p
== beg
? (wchar_t*)str
: (wchar_t*)p
);
597 err
= fpnum_double(&fp
, &ret
);
598 if(err
) *_errno() = err
;
602 /*********************************************************************
603 * wcsrtombs_l (INTERNAL)
605 static size_t wcsrtombs_l(char *mbstr
, const wchar_t **wcstr
,
606 size_t count
, _locale_t locale
)
608 pthreadlocinfo locinfo
;
610 BOOL used_default
= FALSE
;
614 locinfo
= get_locinfo();
616 locinfo
= locale
->locinfo
;
618 if(!locinfo
->lc_codepage
) {
622 return wcslen(*wcstr
);
624 for(i
=0; i
<count
; i
++) {
625 if((*wcstr
)[i
] > 255) {
630 mbstr
[i
] = (*wcstr
)[i
];
631 if(!(*wcstr
)[i
]) break;
634 if(i
< count
) *wcstr
= NULL
;
639 pused_default
= (locinfo
->lc_codepage
!= CP_UTF8
? &used_default
: NULL
);
642 tmp
= WideCharToMultiByte(locinfo
->lc_codepage
, WC_NO_BEST_FIT_CHARS
,
643 *wcstr
, -1, NULL
, 0, NULL
, pused_default
);
644 if(!tmp
|| used_default
) {
655 size
= WideCharToMultiByte(locinfo
->lc_codepage
, WC_NO_BEST_FIT_CHARS
,
656 *wcstr
, 1, buf
, 3, NULL
, pused_default
);
657 if(!size
|| used_default
) {
664 for(i
=0; i
<size
; i
++)
665 mbstr
[tmp
++] = buf
[i
];
676 /*********************************************************************
677 * _wcstombs_l (MSVCRT.@)
679 size_t CDECL
_wcstombs_l(char *mbstr
, const wchar_t *wcstr
,
680 size_t count
, _locale_t locale
)
682 return wcsrtombs_l(mbstr
, &wcstr
, count
, locale
);
685 /*********************************************************************
686 * wcstombs (MSVCRT.@)
688 size_t CDECL
wcstombs(char *mbstr
, const wchar_t *wcstr
,
691 return wcsrtombs_l(mbstr
, &wcstr
, count
, NULL
);
694 /*********************************************************************
695 * wcsrtombs (MSVCRT.@)
697 size_t CDECL
wcsrtombs(char *mbstr
, const wchar_t **wcstr
,
698 size_t count
, mbstate_t *mbstate
)
703 return wcsrtombs_l(mbstr
, wcstr
, count
, NULL
);
706 /*********************************************************************
707 * wcsrtombs_s_l (INTERNAL)
709 static int wcsrtombs_s_l(size_t *ret
, char *mbstr
, size_t size
,
710 const wchar_t **wcstr
, size_t count
, _locale_t locale
)
715 if(!mbstr
&& !size
&& wcstr
) {
716 conv
= wcsrtombs_l(NULL
, wcstr
, 0, locale
);
724 if (!MSVCRT_CHECK_PMT(mbstr
!= NULL
)) return EINVAL
;
725 if (size
) mbstr
[0] = '\0';
726 if (!MSVCRT_CHECK_PMT(wcstr
!= NULL
)) return EINVAL
;
727 if (!MSVCRT_CHECK_PMT(*wcstr
!= NULL
)) return EINVAL
;
729 if(count
==_TRUNCATE
|| size
<count
)
735 conv
= wcsrtombs_l(mbstr
, wcstr
, conv
, locale
);
741 }else if(conv
< size
)
742 mbstr
[conv
++] = '\0';
743 else if(conv
==size
&& (count
==_TRUNCATE
|| mbstr
[conv
-1]=='\0')) {
744 mbstr
[conv
-1] = '\0';
748 MSVCRT_INVALID_PMT("mbstr[size] is too small", ERANGE
);
760 /*********************************************************************
761 * _wcstombs_s_l (MSVCRT.@)
763 int CDECL
_wcstombs_s_l(size_t *ret
, char *mbstr
, size_t size
,
764 const wchar_t *wcstr
, size_t count
, _locale_t locale
)
766 return wcsrtombs_s_l(ret
, mbstr
, size
, &wcstr
,count
, locale
);
769 /*********************************************************************
770 * wcstombs_s (MSVCRT.@)
772 int CDECL
wcstombs_s(size_t *ret
, char *mbstr
, size_t size
,
773 const wchar_t *wcstr
, size_t count
)
775 return wcsrtombs_s_l(ret
, mbstr
, size
, &wcstr
, count
, NULL
);
778 /*********************************************************************
779 * wcsrtombs_s (MSVCRT.@)
781 int CDECL
wcsrtombs_s(size_t *ret
, char *mbstr
, size_t size
,
782 const wchar_t **wcstr
, size_t count
, mbstate_t *mbstate
)
787 return wcsrtombs_s_l(ret
, mbstr
, size
, wcstr
, count
, NULL
);
790 /*********************************************************************
793 double CDECL
wcstod(const wchar_t* lpszStr
, wchar_t** end
)
795 return _wcstod_l(lpszStr
, end
, NULL
);
798 /*********************************************************************
801 double CDECL
_wtof(const wchar_t *str
)
803 return _wcstod_l(str
, NULL
, NULL
);
806 /*********************************************************************
809 double CDECL
_wtof_l(const wchar_t *str
, _locale_t locale
)
811 return _wcstod_l(str
, NULL
, locale
);
816 /*********************************************************************
817 * _wcstof_l (MSVCR120.@)
819 float CDECL
_wcstof_l( const wchar_t *str
, wchar_t **end
, _locale_t locale
)
821 double ret
= _wcstod_l(str
, end
, locale
);
822 if (ret
&& isfinite(ret
)) {
824 if (!f
|| !isfinite(f
))
830 /*********************************************************************
831 * wcstof (MSVCR120.@)
833 float CDECL
wcstof( const wchar_t *str
, wchar_t **end
)
835 return _wcstof_l(str
, end
, NULL
);
838 #endif /* _MSVCR_VER>=120 */
840 /*********************************************************************
841 * arg_clbk_valist (INTERNAL)
843 printf_arg
arg_clbk_valist(void *ctx
, int arg_pos
, int type
, va_list *valist
)
848 ret
.get_longlong
= va_arg(*valist
, LONGLONG
);
849 else if(type
== VT_INT
)
850 ret
.get_int
= va_arg(*valist
, int);
851 else if(type
== VT_R8
)
852 ret
.get_double
= va_arg(*valist
, double);
853 else if(type
== VT_PTR
)
854 ret
.get_ptr
= va_arg(*valist
, void*);
856 ERR("Incorrect type\n");
863 /*********************************************************************
864 * arg_clbk_positional (INTERNAL)
866 printf_arg
arg_clbk_positional(void *ctx
, int pos
, int type
, va_list *valist
)
868 printf_arg
*args
= ctx
;
874 /*********************************************************************
875 * _vsnprintf (MSVCRT.@)
877 int CDECL
_vsnprintf( char *str
, size_t len
, const char *format
, va_list valist
)
879 static const char nullbyte
= '\0';
880 struct _str_ctx_a ctx
= {len
, str
};
883 ret
= pf_printf_a(puts_clbk_str_a
, &ctx
, format
, NULL
, 0,
884 arg_clbk_valist
, NULL
, &valist
);
885 puts_clbk_str_a(&ctx
, 1, &nullbyte
);
891 static int puts_clbk_str_c99_a(void *ctx
, int len
, const char *str
)
893 struct _str_ctx_a
*out
= ctx
;
899 memmove(out
->buf
, str
, out
->len
);
900 out
->buf
+= out
->len
;
905 memmove(out
->buf
, str
, len
);
911 /*********************************************************************
912 * __stdio_common_vsprintf (UCRTBASE.@)
914 int CDECL
__stdio_common_vsprintf( unsigned __int64 options
, char *str
, size_t len
, const char *format
,
915 _locale_t locale
, va_list valist
)
917 static const char nullbyte
= '\0';
918 struct _str_ctx_a ctx
= {len
, str
};
921 if (options
& ~UCRTBASE_PRINTF_MASK
)
922 FIXME("options %s not handled\n", wine_dbgstr_longlong(options
));
923 ret
= pf_printf_a(puts_clbk_str_c99_a
,
924 &ctx
, format
, (_locale_t
)locale
, options
& UCRTBASE_PRINTF_MASK
, arg_clbk_valist
, NULL
, &valist
);
925 puts_clbk_str_a(&ctx
, 1, &nullbyte
);
929 if(options
& _CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION
)
930 return ret
>len
? -1 : ret
;
932 if(len
) str
[len
-1] = 0;
933 if(options
& _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR
)
935 return len
> 0 ? -2 : -1;
940 #endif /* _MSVCR_VER>=140 */
942 /*********************************************************************
943 * _vsnprintf_l (MSVCRT.@)
945 int CDECL
_vsnprintf_l( char *str
, size_t len
, const char *format
,
946 _locale_t locale
, va_list valist
)
948 static const char nullbyte
= '\0';
949 struct _str_ctx_a ctx
= {len
, str
};
952 ret
= pf_printf_a(puts_clbk_str_a
, &ctx
, format
, locale
, 0,
953 arg_clbk_valist
, NULL
, &valist
);
954 puts_clbk_str_a(&ctx
, 1, &nullbyte
);
958 /*********************************************************************
959 * _vsprintf_l (MSVCRT.@)
961 int CDECL
_vsprintf_l( char *str
, const char *format
,
962 _locale_t locale
, va_list valist
)
964 return _vsnprintf_l(str
, INT_MAX
, format
, locale
, valist
);
967 /*********************************************************************
968 * _sprintf_l (MSVCRT.@)
970 int WINAPIV
_sprintf_l(char *str
, const char *format
,
971 _locale_t locale
, ...)
975 va_start(valist
, locale
);
976 retval
= _vsnprintf_l(str
, INT_MAX
, format
, locale
, valist
);
981 static int CDECL
vsnprintf_s_l_opt( char *str
, size_t sizeOfBuffer
,
982 size_t count
, const char *format
, DWORD options
,
983 _locale_t locale
, va_list valist
)
985 static const char nullbyte
= '\0';
986 struct _str_ctx_a ctx
;
989 if(sizeOfBuffer
<count
+1 || count
==-1)
996 ret
= pf_printf_a(puts_clbk_str_a
, &ctx
, format
, locale
, MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER
| options
,
997 arg_clbk_valist
, NULL
, &valist
);
998 puts_clbk_str_a(&ctx
, 1, &nullbyte
);
1000 if(ret
<0 || ret
==len
) {
1001 if(count
!=_TRUNCATE
&& count
>sizeOfBuffer
) {
1002 MSVCRT_INVALID_PMT("str[sizeOfBuffer] is too small", ERANGE
);
1003 memset(str
, 0, sizeOfBuffer
);
1013 static int vsnwprintf_s_l_opt( wchar_t *str
, size_t sizeOfBuffer
,
1014 size_t count
, const wchar_t *format
, DWORD options
,
1015 _locale_t locale
, va_list valist
)
1017 struct _str_ctx_w ctx
;
1021 if(count
!=-1 && len
>count
+1)
1026 ret
= pf_printf_w(puts_clbk_str_w
, &ctx
, format
, locale
, MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER
| options
,
1027 arg_clbk_valist
, NULL
, &valist
);
1028 puts_clbk_str_w(&ctx
, 1, L
"");
1030 if(ret
<0 || ret
==len
) {
1031 if(count
!=_TRUNCATE
&& count
>sizeOfBuffer
) {
1032 MSVCRT_INVALID_PMT("str[sizeOfBuffer] is too small", ERANGE
);
1033 memset(str
, 0, sizeOfBuffer
*sizeof(wchar_t));
1043 /*********************************************************************
1044 * _vsnprintf_s_l (MSVCRT.@)
1046 int CDECL
_vsnprintf_s_l( char *str
, size_t sizeOfBuffer
,
1047 size_t count
, const char *format
,
1048 _locale_t locale
, va_list valist
)
1050 return vsnprintf_s_l_opt(str
, sizeOfBuffer
, count
, format
, 0, locale
, valist
);
1053 /*********************************************************************
1054 * _vsprintf_s_l (MSVCRT.@)
1056 int CDECL
_vsprintf_s_l( char *str
, size_t count
, const char *format
,
1057 _locale_t locale
, va_list valist
)
1059 return _vsnprintf_s_l(str
, INT_MAX
, count
, format
, locale
, valist
);
1062 /*********************************************************************
1063 * _sprintf_s_l (MSVCRT.@)
1065 int WINAPIV
_sprintf_s_l( char *str
, size_t count
, const char *format
,
1066 _locale_t locale
, ...)
1070 va_start(valist
, locale
);
1071 retval
= _vsnprintf_s_l(str
, INT_MAX
, count
, format
, locale
, valist
);
1076 /*********************************************************************
1077 * _vsnprintf_s (MSVCRT.@)
1079 int CDECL
_vsnprintf_s( char *str
, size_t sizeOfBuffer
,
1080 size_t count
, const char *format
, va_list valist
)
1082 return _vsnprintf_s_l(str
,sizeOfBuffer
, count
, format
, NULL
, valist
);
1085 /*********************************************************************
1086 * _vsnprintf_c_l (MSVCRT.@)
1088 int CDECL
_vsnprintf_c_l(char *str
, size_t len
, const char *format
,
1089 _locale_t locale
, va_list valist
)
1091 return vsnprintf_s_l_opt(str
, len
, len
, format
, 0, locale
, valist
);
1094 /*********************************************************************
1095 * _vsnprintf_c (MSVCRT.@)
1097 int CDECL
_vsnprintf_c(char *str
, size_t len
,
1098 const char *format
, va_list valist
)
1100 return _vsnprintf_c_l(str
, len
, format
, NULL
, valist
);
1105 /*********************************************************************
1106 * __stdio_common_vsnprintf_s (UCRTBASE.@)
1108 int CDECL
__stdio_common_vsnprintf_s( unsigned __int64 options
,
1109 char *str
, size_t sizeOfBuffer
, size_t count
,
1110 const char *format
, _locale_t locale
, va_list valist
)
1112 if (options
& ~UCRTBASE_PRINTF_MASK
)
1113 FIXME("options %s not handled\n", wine_dbgstr_longlong(options
));
1114 return vsnprintf_s_l_opt(str
, sizeOfBuffer
, count
, format
, options
& UCRTBASE_PRINTF_MASK
, locale
, valist
);
1117 /*********************************************************************
1118 * __stdio_common_vsnwprintf_s (UCRTBASE.@)
1120 int CDECL
__stdio_common_vsnwprintf_s( unsigned __int64 options
,
1121 wchar_t *str
, size_t sizeOfBuffer
, size_t count
,
1122 const wchar_t *format
, _locale_t locale
, va_list valist
)
1124 if (options
& ~UCRTBASE_PRINTF_MASK
)
1125 FIXME("options %s not handled\n", wine_dbgstr_longlong(options
));
1126 return vsnwprintf_s_l_opt(str
, sizeOfBuffer
, count
, format
, options
& UCRTBASE_PRINTF_MASK
, locale
, valist
);
1129 /*********************************************************************
1130 * __stdio_common_vswprintf_s (UCRTBASE.@)
1132 int CDECL
__stdio_common_vswprintf_s( unsigned __int64 options
,
1133 wchar_t *str
, size_t count
, const wchar_t *format
,
1134 _locale_t locale
, va_list valist
)
1136 return __stdio_common_vsnwprintf_s(options
, str
, INT_MAX
, count
, format
, locale
, valist
);
1139 /*********************************************************************
1140 * __stdio_common_vsprintf_s (UCRTBASE.@)
1142 int CDECL
__stdio_common_vsprintf_s( unsigned __int64 options
,
1143 char *str
, size_t count
, const char *format
,
1144 _locale_t locale
, va_list valist
)
1146 if (options
& ~UCRTBASE_PRINTF_MASK
)
1147 FIXME("options %s not handled\n", wine_dbgstr_longlong(options
));
1148 return vsnprintf_s_l_opt(str
, INT_MAX
, count
, format
, options
& UCRTBASE_PRINTF_MASK
, locale
, valist
);
1151 #endif /* _MSVCR_VER>=140 */
1153 /*********************************************************************
1154 * vsprintf (MSVCRT.@)
1156 int CDECL
vsprintf( char *str
, const char *format
, va_list valist
)
1158 return vsnprintf(str
, INT_MAX
, format
, valist
);
1161 /*********************************************************************
1162 * vsprintf_s (MSVCRT.@)
1164 int CDECL
vsprintf_s( char *str
, size_t num
, const char *format
, va_list valist
)
1166 return vsnprintf(str
, num
, format
, valist
);
1169 /*********************************************************************
1170 * _vscprintf (MSVCRT.@)
1172 int CDECL
_vscprintf( const char *format
, va_list valist
)
1174 return _vsnprintf_l( NULL
, INT_MAX
, format
, NULL
, valist
);
1177 /*********************************************************************
1178 * _vscprintf_l (MSVCRT.@)
1180 int CDECL
_vscprintf_l(const char *format
,
1181 _locale_t locale
, va_list valist
)
1183 return _vsnprintf_l(NULL
, INT_MAX
, format
, locale
, valist
);
1186 /*********************************************************************
1187 * _vscprintf_p_l (MSVCRT.@)
1189 int CDECL
_vscprintf_p_l(const char *format
,
1190 _locale_t locale
, va_list args
)
1192 printf_arg args_ctx
[_ARGMAX
+1];
1193 struct _str_ctx_a puts_ctx
= {INT_MAX
, NULL
};
1196 memset(args_ctx
, 0, sizeof(args_ctx
));
1198 ret
= create_positional_ctx_a(args_ctx
, format
, args
);
1200 _invalid_parameter(NULL
, NULL
, NULL
, 0, 0);
1203 } else if(ret
== 0) {
1204 ret
= pf_printf_a(puts_clbk_str_a
, &puts_ctx
, format
, locale
,
1205 MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER
,
1206 arg_clbk_valist
, NULL
, &args
);
1208 ret
= pf_printf_a(puts_clbk_str_a
, &puts_ctx
, format
, locale
,
1209 MSVCRT_PRINTF_POSITIONAL_PARAMS
| MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER
,
1210 arg_clbk_positional
, args_ctx
, NULL
);
1216 /*********************************************************************
1217 * _vscprintf_p (MSVCR80.@)
1219 int CDECL
_vscprintf_p(const char *format
, va_list argptr
)
1221 return _vscprintf_p_l(format
, NULL
, argptr
);
1224 /*********************************************************************
1225 * _snprintf (MSVCRT.@)
1227 int WINAPIV
_snprintf(char *str
, size_t len
, const char *format
, ...)
1231 va_start(valist
, format
);
1232 retval
= vsnprintf(str
, len
, format
, valist
);
1237 /*********************************************************************
1238 * _snprintf_l (MSVCRT.@)
1240 int WINAPIV
_snprintf_l(char *str
, size_t count
, const char *format
,
1241 _locale_t locale
, ...)
1245 va_start(valist
, locale
);
1246 retval
= _vsnprintf_l(str
, count
, format
, locale
, valist
);
1251 /*********************************************************************
1252 * _snprintf_c_l (MSVCRT.@)
1254 int WINAPIV
_snprintf_c_l(char *str
, size_t count
, const char *format
,
1255 _locale_t locale
, ...)
1259 va_start(valist
, locale
);
1260 retval
= _vsnprintf_c_l(str
, count
, format
, locale
, valist
);
1265 /*********************************************************************
1266 * _snprintf_c (MSVCRT.@)
1268 int WINAPIV
_snprintf_c(char *str
, size_t count
, const char *format
, ...)
1272 va_start(valist
, format
);
1273 retval
= _vsnprintf_c(str
, count
, format
, valist
);
1278 /*********************************************************************
1279 * _snprintf_s_l (MSVCRT.@)
1281 int WINAPIV
_snprintf_s_l(char *str
, size_t len
, size_t count
,
1282 const char *format
, _locale_t locale
, ...)
1286 va_start(valist
, locale
);
1287 retval
= _vsnprintf_s_l(str
, len
, count
, format
, locale
, valist
);
1292 /*********************************************************************
1293 * _snprintf_s (MSVCRT.@)
1295 int WINAPIV
_snprintf_s(char *str
, size_t len
, size_t count
,
1296 const char *format
, ...)
1300 va_start(valist
, format
);
1301 retval
= _vsnprintf_s_l(str
, len
, count
, format
, NULL
, valist
);
1306 /*********************************************************************
1307 * _scprintf (MSVCRT.@)
1309 int WINAPIV
_scprintf(const char *format
, ...)
1313 va_start(valist
, format
);
1314 retval
= _vscprintf(format
, valist
);
1319 /*********************************************************************
1320 * _vsnwprintf (MSVCRT.@)
1322 int CDECL
_vsnwprintf(wchar_t *str
, size_t len
,
1323 const wchar_t *format
, va_list valist
)
1325 struct _str_ctx_w ctx
= {len
, str
};
1328 ret
= pf_printf_w(puts_clbk_str_w
, &ctx
, format
, NULL
, 0,
1329 arg_clbk_valist
, NULL
, &valist
);
1330 puts_clbk_str_w(&ctx
, 1, L
"");
1334 /*********************************************************************
1335 * _vsnwprintf_l (MSVCRT.@)
1337 int CDECL
_vsnwprintf_l(wchar_t *str
, size_t len
, const wchar_t *format
,
1338 _locale_t locale
, va_list valist
)
1340 struct _str_ctx_w ctx
= {len
, str
};
1343 ret
= pf_printf_w(puts_clbk_str_w
, &ctx
, format
, locale
, 0,
1344 arg_clbk_valist
, NULL
, &valist
);
1345 puts_clbk_str_w(&ctx
, 1, L
"");
1349 /*********************************************************************
1350 * _vswprintf_c_l (MSVCRT.@)
1352 int CDECL
_vswprintf_c_l(wchar_t *str
, size_t len
, const wchar_t *format
,
1353 _locale_t locale
, va_list valist
)
1355 return vsnwprintf_s_l_opt(str
, len
, len
, format
, 0, locale
, valist
);
1358 /*********************************************************************
1359 * _vswprintf_c (MSVCRT.@)
1361 int CDECL
_vswprintf_c(wchar_t *str
, size_t len
,
1362 const wchar_t *format
, va_list valist
)
1364 return _vswprintf_c_l(str
, len
, format
, NULL
, valist
);
1367 static int vswprintf_p_l_opt(wchar_t *buffer
, size_t length
,
1368 const wchar_t *format
, DWORD options
, _locale_t locale
, va_list args
)
1370 printf_arg args_ctx
[_ARGMAX
+1];
1371 struct _str_ctx_w puts_ctx
= {length
, buffer
};
1374 memset(args_ctx
, 0, sizeof(args_ctx
));
1376 ret
= create_positional_ctx_w(args_ctx
, format
, args
);
1378 _invalid_parameter(NULL
, NULL
, NULL
, 0, 0);
1382 ret
= pf_printf_w(puts_clbk_str_w
, &puts_ctx
, format
, locale
, MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER
| options
,
1383 arg_clbk_valist
, NULL
, &args
);
1385 ret
= pf_printf_w(puts_clbk_str_w
, &puts_ctx
, format
, locale
,
1386 MSVCRT_PRINTF_POSITIONAL_PARAMS
| MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER
| options
,
1387 arg_clbk_positional
, args_ctx
, NULL
);
1389 puts_clbk_str_w(&puts_ctx
, 1, L
"");
1393 /*********************************************************************
1394 * _vswprintf_p_l (MSVCRT.@)
1396 int CDECL
_vswprintf_p_l(wchar_t *buffer
, size_t length
,
1397 const wchar_t *format
, _locale_t locale
, va_list args
)
1399 return vswprintf_p_l_opt(buffer
, length
, format
, 0, locale
, args
);
1403 /*********************************************************************
1404 * _vswprintf_p (MSVCR80.@)
1406 int CDECL
_vswprintf_p(wchar_t *buffer
, size_t length
,
1407 const wchar_t *format
, va_list args
)
1409 return vswprintf_p_l_opt(buffer
, length
, format
, 0, NULL
, args
);
1414 /*********************************************************************
1415 * __stdio_common_vswprintf_p (UCRTBASE.@)
1417 int CDECL
__stdio_common_vswprintf_p( unsigned __int64 options
,
1418 wchar_t *str
, size_t count
, const wchar_t *format
,
1419 _locale_t locale
, va_list valist
)
1421 if (options
& ~UCRTBASE_PRINTF_MASK
)
1422 FIXME("options %s not handled\n", wine_dbgstr_longlong(options
));
1423 return vswprintf_p_l_opt(str
, count
, format
, options
& UCRTBASE_PRINTF_MASK
, locale
, valist
);
1427 /*********************************************************************
1428 * _vsnwprintf_s_l (MSVCRT.@)
1430 int CDECL
_vsnwprintf_s_l( wchar_t *str
, size_t sizeOfBuffer
,
1431 size_t count
, const wchar_t *format
,
1432 _locale_t locale
, va_list valist
)
1434 return vsnwprintf_s_l_opt(str
, sizeOfBuffer
, count
, format
, 0, locale
, valist
);
1437 /*********************************************************************
1438 * _vsnwprintf_s (MSVCRT.@)
1440 int CDECL
_vsnwprintf_s(wchar_t *str
, size_t sizeOfBuffer
,
1441 size_t count
, const wchar_t *format
, va_list valist
)
1443 return _vsnwprintf_s_l(str
, sizeOfBuffer
, count
,
1444 format
, NULL
, valist
);
1447 /*********************************************************************
1448 * _snwprintf (MSVCRT.@)
1450 int WINAPIV
_snwprintf( wchar_t *str
, size_t len
, const wchar_t *format
, ...)
1454 va_start(valist
, format
);
1455 retval
= _vsnwprintf(str
, len
, format
, valist
);
1460 /*********************************************************************
1461 * _snwprintf_l (MSVCRT.@)
1463 int WINAPIV
_snwprintf_l( wchar_t *str
, size_t len
, const wchar_t *format
,
1464 _locale_t locale
, ...)
1468 va_start(valist
, locale
);
1469 retval
= _vsnwprintf_l(str
, len
, format
, locale
, valist
);
1474 /*********************************************************************
1475 * _snwprintf_s (MSVCRT.@)
1477 int WINAPIV
_snwprintf_s( wchar_t *str
, size_t len
, size_t count
,
1478 const wchar_t *format
, ...)
1482 va_start(valist
, format
);
1483 retval
= _vsnwprintf_s_l(str
, len
, count
, format
, NULL
, valist
);
1488 /*********************************************************************
1489 * _snwprintf_s_l (MSVCRT.@)
1491 int WINAPIV
_snwprintf_s_l( wchar_t *str
, size_t len
, size_t count
,
1492 const wchar_t *format
, _locale_t locale
, ... )
1496 va_start(valist
, locale
);
1497 retval
= _vsnwprintf_s_l(str
, len
, count
, format
, locale
, valist
);
1504 static int puts_clbk_str_c99_w(void *ctx
, int len
, const wchar_t *str
)
1506 struct _str_ctx_w
*out
= ctx
;
1511 if(out
->len
< len
) {
1512 memcpy(out
->buf
, str
, out
->len
*sizeof(wchar_t));
1513 out
->buf
+= out
->len
;
1518 memcpy(out
->buf
, str
, len
*sizeof(wchar_t));
1524 /*********************************************************************
1525 * __stdio_common_vswprintf (UCRTBASE.@)
1527 int CDECL
__stdio_common_vswprintf( unsigned __int64 options
,
1528 wchar_t *str
, size_t len
, const wchar_t *format
,
1529 _locale_t locale
, va_list valist
)
1531 struct _str_ctx_w ctx
= {len
, str
};
1534 if (options
& ~UCRTBASE_PRINTF_MASK
)
1535 FIXME("options %s not handled\n", wine_dbgstr_longlong(options
));
1536 ret
= pf_printf_w(puts_clbk_str_c99_w
,
1537 &ctx
, format
, locale
, options
& UCRTBASE_PRINTF_MASK
, arg_clbk_valist
, NULL
, &valist
);
1538 puts_clbk_str_w(&ctx
, 1, L
"");
1542 if(options
& _CRT_INTERNAL_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION
)
1543 return ret
>len
? -1 : ret
;
1545 if(len
) str
[len
-1] = 0;
1546 if(options
& _CRT_INTERNAL_PRINTF_STANDARD_SNPRINTF_BEHAVIOR
)
1548 return len
> 0 ? -2 : -1;
1553 #endif /* _MSVCR_VER>=140 */
1555 /*********************************************************************
1556 * sprintf (MSVCRT.@)
1558 int WINAPIV
sprintf( char *str
, const char *format
, ... )
1563 va_start( ap
, format
);
1564 r
= vsnprintf( str
, INT_MAX
, format
, ap
);
1569 /*********************************************************************
1570 * sprintf_s (MSVCRT.@)
1572 int WINAPIV
sprintf_s( char *str
, size_t num
, const char *format
, ... )
1577 va_start( ap
, format
);
1578 r
= vsnprintf( str
, num
, format
, ap
);
1583 /*********************************************************************
1584 * _scwprintf (MSVCRT.@)
1586 int WINAPIV
_scwprintf( const wchar_t *format
, ... )
1591 va_start( ap
, format
);
1592 r
= _vsnwprintf( NULL
, INT_MAX
, format
, ap
);
1597 /*********************************************************************
1598 * swprintf (MSVCRT.@)
1600 int WINAPIV
_swprintf( wchar_t *str
, const wchar_t *format
, ... )
1605 va_start( ap
, format
);
1606 r
= _vsnwprintf( str
, INT_MAX
, format
, ap
);
1611 /*********************************************************************
1612 * swprintf_s (MSVCRT.@)
1614 int WINAPIV
swprintf_s(wchar_t *str
, size_t numberOfElements
,
1615 const wchar_t *format
, ... )
1620 va_start(ap
, format
);
1621 r
= _vsnwprintf_s(str
, numberOfElements
, INT_MAX
, format
, ap
);
1627 /*********************************************************************
1628 * _swprintf_s_l (MSVCRT.@)
1630 int WINAPIV
_swprintf_s_l(wchar_t *str
, size_t numberOfElements
,
1631 const wchar_t *format
, _locale_t locale
, ... )
1636 va_start(ap
, locale
);
1637 r
= _vsnwprintf_s_l(str
, numberOfElements
, INT_MAX
, format
, locale
, ap
);
1643 /*********************************************************************
1644 * _swprintf_c_l (MSVCRT.@)
1646 int WINAPIV
_swprintf_c_l(wchar_t *str
, size_t len
,
1647 const wchar_t *format
, _locale_t locale
, ... )
1652 va_start(ap
, locale
);
1653 r
= _vswprintf_c_l(str
, len
, format
, locale
, ap
);
1659 /*********************************************************************
1660 * _swprintf_c (MSVCRT.@)
1662 int WINAPIV
_swprintf_c(wchar_t *str
, size_t len
,
1663 const wchar_t *format
, ... )
1668 va_start(ap
, format
);
1669 r
= _vswprintf_c(str
, len
, format
, ap
);
1675 /*********************************************************************
1676 * _vswprintf (MSVCRT.@)
1678 int CDECL
_vswprintf( wchar_t* str
, const wchar_t* format
, va_list args
)
1680 return _vsnwprintf( str
, INT_MAX
, format
, args
);
1683 /*********************************************************************
1684 * _vswprintf (MSVCRT.@)
1686 int CDECL
_vswprintf_l( wchar_t* str
, const wchar_t* format
,
1687 _locale_t locale
, va_list args
)
1689 return _vsnwprintf_l( str
, INT_MAX
, format
, locale
, args
);
1692 /*********************************************************************
1693 * _vscwprintf (MSVCRT.@)
1695 int CDECL
_vscwprintf( const wchar_t *format
, va_list args
)
1697 return _vsnwprintf( NULL
, INT_MAX
, format
, args
);
1700 /*********************************************************************
1701 * _vscwprintf_l (MSVCRT.@)
1703 int CDECL
_vscwprintf_l( const wchar_t *format
, _locale_t locale
, va_list args
)
1705 return _vsnwprintf_l( NULL
, INT_MAX
, format
, locale
, args
);
1708 /*********************************************************************
1709 * _vscwprintf_p_l (MSVCRT.@)
1711 int CDECL
_vscwprintf_p_l( const wchar_t *format
, _locale_t locale
, va_list args
)
1713 return vswprintf_p_l_opt( NULL
, INT_MAX
, format
, 0, locale
, args
);
1717 /*********************************************************************
1718 * _vscwprintf_p (MSVCR80.@)
1720 int CDECL
_vscwprintf_p(const wchar_t *format
, va_list args
)
1722 return vswprintf_p_l_opt(NULL
, INT_MAX
, format
, 0, NULL
, args
);
1726 /*********************************************************************
1727 * vswprintf_s (MSVCRT.@)
1729 int CDECL
vswprintf_s(wchar_t* str
, size_t numberOfElements
,
1730 const wchar_t* format
, va_list args
)
1732 return _vsnwprintf_s(str
, numberOfElements
, INT_MAX
, format
, args
);
1735 /*********************************************************************
1736 * _vswprintf_s_l (MSVCRT.@)
1738 int CDECL
_vswprintf_s_l(wchar_t* str
, size_t numberOfElements
,
1739 const wchar_t* format
, _locale_t locale
, va_list args
)
1741 return _vsnwprintf_s_l(str
, numberOfElements
, INT_MAX
,
1742 format
, locale
, args
);
1745 static int vsprintf_p_l_opt(char *buffer
, size_t length
, const char *format
,
1746 DWORD options
, _locale_t locale
, va_list args
)
1748 static const char nullbyte
= '\0';
1749 printf_arg args_ctx
[_ARGMAX
+1];
1750 struct _str_ctx_a puts_ctx
= {length
, buffer
};
1753 memset(args_ctx
, 0, sizeof(args_ctx
));
1755 ret
= create_positional_ctx_a(args_ctx
, format
, args
);
1757 _invalid_parameter(NULL
, NULL
, NULL
, 0, 0);
1761 ret
= pf_printf_a(puts_clbk_str_a
, &puts_ctx
, format
, locale
,
1762 MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER
| options
, arg_clbk_valist
, NULL
, &args
);
1764 ret
= pf_printf_a(puts_clbk_str_a
, &puts_ctx
, format
, locale
,
1765 MSVCRT_PRINTF_POSITIONAL_PARAMS
| MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER
| options
,
1766 arg_clbk_positional
, args_ctx
, NULL
);
1768 puts_clbk_str_a(&puts_ctx
, 1, &nullbyte
);
1772 /*********************************************************************
1773 * _vsprintf_p_l (MSVCRT.@)
1775 int CDECL
_vsprintf_p_l(char *buffer
, size_t length
, const char *format
,
1776 _locale_t locale
, va_list args
)
1778 return vsprintf_p_l_opt(buffer
, length
, format
, 0, locale
, args
);
1781 /*********************************************************************
1782 * _vsprintf_p (MSVCRT.@)
1784 int CDECL
_vsprintf_p(char *buffer
, size_t length
,
1785 const char *format
, va_list args
)
1787 return _vsprintf_p_l(buffer
, length
, format
, NULL
, args
);
1791 /*********************************************************************
1792 * __stdio_common_vsprintf_p (UCRTBASE.@)
1794 int CDECL
__stdio_common_vsprintf_p(unsigned __int64 options
, char *buffer
, size_t length
,
1795 const char *format
, _locale_t locale
, va_list args
)
1797 if (options
& ~UCRTBASE_PRINTF_MASK
)
1798 FIXME("options %s not handled\n", wine_dbgstr_longlong(options
));
1799 return vsprintf_p_l_opt(buffer
, length
, format
, options
& UCRTBASE_PRINTF_MASK
, locale
, args
);
1803 /*********************************************************************
1804 * _sprintf_p_l (MSVCRT.@)
1806 int WINAPIV
_sprintf_p_l(char *buffer
, size_t length
,
1807 const char *format
, _locale_t locale
, ...)
1812 va_start(valist
, locale
);
1813 r
= _vsprintf_p_l(buffer
, length
, format
, locale
, valist
);
1819 /*********************************************************************
1820 * __swprintf_l (MSVCRT.@)
1822 int WINAPIV
__swprintf_l( wchar_t *str
, const wchar_t *format
,
1823 _locale_t locale
, ...)
1827 va_start(valist
, locale
);
1828 retval
= _vswprintf_l(str
, format
, locale
, valist
);
1834 /*********************************************************************
1835 * _sprintf_p (MSVCR80.@)
1837 int WINAPIV
_sprintf_p(char *buffer
, size_t length
, const char *format
, ...)
1842 va_start(valist
, format
);
1843 r
= _vsprintf_p_l(buffer
, length
, format
, NULL
, valist
);
1850 /*********************************************************************
1851 * _swprintf_p_l (MSVCRT.@)
1853 int WINAPIV
_swprintf_p_l(wchar_t *buffer
, size_t length
,
1854 const wchar_t *format
, _locale_t locale
, ...)
1859 va_start(valist
, locale
);
1860 r
= vswprintf_p_l_opt(buffer
, length
, format
, 0, locale
, valist
);
1866 /*********************************************************************
1869 int CDECL
wcscmp(const wchar_t *str1
, const wchar_t *str2
)
1871 while (*str1
&& (*str1
== *str2
))
1884 /*********************************************************************
1885 * _wcscoll_l (MSVCRT.@)
1887 int CDECL
_wcscoll_l(const wchar_t* str1
, const wchar_t* str2
, _locale_t locale
)
1889 pthreadlocinfo locinfo
;
1892 locinfo
= get_locinfo();
1894 locinfo
= locale
->locinfo
;
1896 if(!locinfo
->lc_handle
[LC_COLLATE
])
1897 return wcscmp(str1
, str2
);
1898 return CompareStringW(locinfo
->lc_handle
[LC_COLLATE
], 0, str1
, -1, str2
, -1)-CSTR_EQUAL
;
1901 /*********************************************************************
1902 * wcscoll (MSVCRT.@)
1904 int CDECL
wcscoll( const wchar_t* str1
, const wchar_t* str2
)
1906 return _wcscoll_l(str1
, str2
, NULL
);
1909 /*********************************************************************
1910 * wcspbrk (MSVCRT.@)
1912 wchar_t* CDECL
wcspbrk( const wchar_t* str
, const wchar_t* accept
)
1918 for (p
= accept
; *p
; p
++) if (*p
== *str
) return (wchar_t*)str
;
1924 /*********************************************************************
1925 * wcstok_s (MSVCRT.@)
1927 wchar_t * CDECL
wcstok_s( wchar_t *str
, const wchar_t *delim
,
1928 wchar_t **next_token
)
1932 if (!MSVCRT_CHECK_PMT(delim
!= NULL
)) return NULL
;
1933 if (!MSVCRT_CHECK_PMT(next_token
!= NULL
)) return NULL
;
1934 if (!MSVCRT_CHECK_PMT(str
!= NULL
|| *next_token
!= NULL
)) return NULL
;
1936 if (!str
) str
= *next_token
;
1938 while (*str
&& wcschr( delim
, *str
)) str
++;
1939 if (!*str
) ret
= NULL
;
1943 while (*str
&& !wcschr( delim
, *str
)) str
++;
1944 if (*str
) *str
++ = 0;
1950 /*********************************************************************
1954 wchar_t * CDECL
wcstok( wchar_t *str
, const wchar_t *delim
, wchar_t **ctx
)
1957 ctx
= &msvcrt_get_thread_data()->wcstok_next
;
1958 return wcstok_s(str
, delim
, ctx
);
1961 wchar_t * CDECL
wcstok( wchar_t *str
, const wchar_t *delim
)
1963 return wcstok_s(str
, delim
, &msvcrt_get_thread_data()->wcstok_next
);
1967 /*********************************************************************
1968 * _wctomb_s_l (MSVCRT.@)
1970 int CDECL
_wctomb_s_l(int *len
, char *mbchar
, size_t size
,
1971 wchar_t wch
, _locale_t locale
)
1973 pthreadlocinfo locinfo
;
1978 if(!mbchar
&& size
>0) {
1987 if(!MSVCRT_CHECK_PMT(size
<= INT_MAX
))
1991 locinfo
= get_locinfo();
1993 locinfo
= locale
->locinfo
;
1995 if(!locinfo
->lc_codepage
) {
1997 if(mbchar
&& size
>0)
1998 memset(mbchar
, 0, size
);
2003 if(!MSVCRT_CHECK_PMT_ERR(size
>= 1, ERANGE
))
2012 perror
= (locinfo
->lc_codepage
!= CP_UTF8
? &error
: NULL
);
2013 mblen
= WideCharToMultiByte(locinfo
->lc_codepage
, 0, &wch
, 1, mbchar
, size
, NULL
, perror
);
2014 if(!mblen
|| error
) {
2015 if(!mblen
&& GetLastError()==ERROR_INSUFFICIENT_BUFFER
) {
2016 if(mbchar
&& size
>0)
2017 memset(mbchar
, 0, size
);
2019 MSVCRT_INVALID_PMT("insufficient buffer size", ERANGE
);
2032 /*********************************************************************
2033 * wctomb_s (MSVCRT.@)
2035 int CDECL
wctomb_s(int *len
, char *mbchar
, size_t size
, wchar_t wch
)
2037 return _wctomb_s_l(len
, mbchar
, size
, wch
, NULL
);
2040 /*********************************************************************
2041 * _wctomb_l (MSVCRT.@)
2043 int CDECL
_wctomb_l(char *dst
, wchar_t ch
, _locale_t locale
)
2047 _wctomb_s_l(&len
, dst
, dst
? MB_LEN_MAX
: 0, ch
, locale
);
2051 /*********************************************************************
2054 INT CDECL
wctomb( char *dst
, wchar_t ch
)
2056 return _wctomb_l(dst
, ch
, NULL
);
2059 /*********************************************************************
2062 INT CDECL
wctob( wint_t wchar
)
2067 UINT codepage
= get_locinfo()->lc_codepage
;
2069 perror
= (codepage
!= CP_UTF8
? &error
: NULL
);
2073 return (signed char)wchar
;
2076 } else if(WideCharToMultiByte( codepage
, 0, &wchar
, 1, &out
, 1, NULL
, perror
) && !error
)
2081 /*********************************************************************
2082 * wcrtomb_s (MSVCRT.@)
2084 INT CDECL
wcrtomb_s(size_t *len
, char *mbchar
,
2085 size_t size
, wchar_t wch
, mbstate_t *s
)
2090 ret
= wctomb_s(&ilen
, mbchar
, size
, wch
);
2091 if (len
) *len
= ilen
;
2095 /*********************************************************************
2096 * wcrtomb (MSVCRT.@)
2098 size_t CDECL
wcrtomb( char *dst
, wchar_t ch
, mbstate_t *s
)
2102 return wctomb(dst
, ch
);
2105 /*********************************************************************
2106 * _iswctype_l (MSVCRT.@)
2108 INT CDECL
_iswctype_l( wchar_t wc
, wctype_t type
, _locale_t locale
)
2112 if (wc
== WEOF
) return 0;
2113 if (wc
< 256) return MSVCRT__pwctype
[wc
] & type
;
2115 if (!GetStringTypeW(CT_CTYPE1
, &wc
, 1, &ct
))
2117 ERR("GetStringTypeW failed for %x\n", wc
);
2123 /*********************************************************************
2124 * iswctype (MSVCRT.@)
2126 INT CDECL
iswctype( wchar_t wc
, wctype_t type
)
2128 return _iswctype_l( wc
, type
, NULL
);
2131 /*********************************************************************
2132 * _iswalnum_l (MSVCRT.@)
2134 int CDECL
_iswalnum_l( wchar_t wc
, _locale_t locale
)
2136 return _iswctype_l( wc
, _ALPHA
| _DIGIT
, locale
);
2139 /*********************************************************************
2140 * iswalnum (MSVCRT.@)
2142 INT CDECL
iswalnum( wchar_t wc
)
2144 return _iswalnum_l( wc
, NULL
);
2147 /*********************************************************************
2148 * iswalpha_l (MSVCRT.@)
2150 INT CDECL
_iswalpha_l( wchar_t wc
, _locale_t locale
)
2152 return _iswctype_l( wc
, _ALPHA
, locale
);
2155 /*********************************************************************
2156 * iswalpha (MSVCRT.@)
2158 INT CDECL
iswalpha( wchar_t wc
)
2160 return _iswalpha_l( wc
, NULL
);
2163 /*********************************************************************
2164 * _iswcntrl_l (MSVCRT.@)
2166 int CDECL
_iswcntrl_l( wchar_t wc
, _locale_t locale
)
2168 return _iswctype_l( wc
, _CONTROL
, locale
);
2171 /*********************************************************************
2172 * iswcntrl (MSVCRT.@)
2174 INT CDECL
iswcntrl( wchar_t wc
)
2176 return _iswcntrl_l( wc
, NULL
);
2179 /*********************************************************************
2180 * _iswdigit_l (MSVCRT.@)
2182 INT CDECL
_iswdigit_l( wchar_t wc
, _locale_t locale
)
2184 return _iswctype_l( wc
, _DIGIT
, locale
);
2187 /*********************************************************************
2188 * iswdigit (MSVCRT.@)
2190 INT CDECL
iswdigit( wchar_t wc
)
2192 return _iswdigit_l( wc
, NULL
);
2195 /*********************************************************************
2196 * _iswgraph_l (MSVCRT.@)
2198 int CDECL
_iswgraph_l( wchar_t wc
, _locale_t locale
)
2200 return _iswctype_l( wc
, _ALPHA
| _DIGIT
| _PUNCT
, locale
);
2203 /*********************************************************************
2204 * iswgraph (MSVCRT.@)
2206 INT CDECL
iswgraph( wchar_t wc
)
2208 return _iswgraph_l( wc
, NULL
);
2211 /*********************************************************************
2212 * _iswlower_l (MSVCRT.@)
2214 int CDECL
_iswlower_l( wchar_t wc
, _locale_t locale
)
2216 return _iswctype_l( wc
, _LOWER
, locale
);
2219 /*********************************************************************
2220 * iswlower (MSVCRT.@)
2222 INT CDECL
iswlower( wchar_t wc
)
2224 return _iswlower_l( wc
, NULL
);
2227 /*********************************************************************
2228 * _iswprint_l (MSVCRT.@)
2230 int CDECL
_iswprint_l( wchar_t wc
, _locale_t locale
)
2232 return _iswctype_l( wc
, _ALPHA
| _BLANK
| _DIGIT
| _PUNCT
, locale
);
2235 /*********************************************************************
2236 * iswprint (MSVCRT.@)
2238 INT CDECL
iswprint( wchar_t wc
)
2240 return _iswprint_l( wc
, NULL
);
2243 /*********************************************************************
2244 * _iswpunct_l (MSVCRT.@)
2246 INT CDECL
_iswpunct_l( wchar_t wc
, _locale_t locale
)
2248 return _iswctype_l( wc
, _PUNCT
, locale
);
2251 /*********************************************************************
2252 * iswpunct (MSVCRT.@)
2254 INT CDECL
iswpunct( wchar_t wc
)
2256 return _iswpunct_l( wc
, NULL
);
2259 /*********************************************************************
2260 * _iswspace_l (MSVCRT.@)
2262 INT CDECL
_iswspace_l( wchar_t wc
, _locale_t locale
)
2264 return _iswctype_l( wc
, _SPACE
, locale
);
2267 /*********************************************************************
2268 * iswspace (MSVCRT.@)
2270 INT CDECL
iswspace( wchar_t wc
)
2272 return _iswspace_l( wc
, NULL
);
2275 /*********************************************************************
2276 * _iswupper_l (MSVCRT.@)
2278 int CDECL
_iswupper_l( wchar_t wc
, _locale_t locale
)
2280 return _iswctype_l( wc
, _UPPER
, locale
);
2283 /*********************************************************************
2284 * iswupper (MSVCRT.@)
2286 INT CDECL
iswupper( wchar_t wc
)
2288 return _iswupper_l( wc
, NULL
);
2291 /*********************************************************************
2292 * _iswxdigit_l (MSVCRT.@)
2294 int CDECL
_iswxdigit_l( wchar_t wc
, _locale_t locale
)
2296 return _iswctype_l( wc
, _HEX
, locale
);
2299 /*********************************************************************
2300 * iswxdigit (MSVCRT.@)
2302 INT CDECL
iswxdigit( wchar_t wc
)
2304 return _iswxdigit_l( wc
, NULL
);
2307 /*********************************************************************
2308 * _iswblank_l (MSVCRT.@)
2310 INT CDECL
_iswblank_l( wchar_t wc
, _locale_t locale
)
2312 return wc
== '\t' || _iswctype_l( wc
, _BLANK
, locale
);
2315 /*********************************************************************
2316 * iswblank (MSVCRT.@)
2318 INT CDECL
iswblank( wchar_t wc
)
2320 return wc
== '\t' || _iswctype_l( wc
, _BLANK
, NULL
);
2323 /*********************************************************************
2324 * wcscpy_s (MSVCRT.@)
2326 INT CDECL
wcscpy_s( wchar_t* wcDest
, size_t numElement
, const wchar_t *wcSrc
)
2330 if(!MSVCRT_CHECK_PMT(wcDest
)) return EINVAL
;
2331 if(!MSVCRT_CHECK_PMT(numElement
)) return EINVAL
;
2333 if(!MSVCRT_CHECK_PMT(wcSrc
))
2339 size
= wcslen(wcSrc
) + 1;
2341 if(!MSVCRT_CHECK_PMT_ERR(size
<= numElement
, ERANGE
))
2347 memmove( wcDest
, wcSrc
, size
*sizeof(WCHAR
) );
2352 /***********************************************************************
2355 wchar_t* __cdecl
wcscpy( wchar_t *dst
, const wchar_t *src
)
2358 while ((*p
++ = *src
++));
2362 /******************************************************************
2363 * wcsncpy (MSVCRT.@)
2365 wchar_t* __cdecl
wcsncpy( wchar_t* s1
, const wchar_t *s2
, size_t n
)
2370 if(!(s1
[i
] = s2
[i
])) break;
2376 /******************************************************************
2377 * wcsncpy_s (MSVCRT.@)
2379 INT CDECL
wcsncpy_s( wchar_t* wcDest
, size_t numElement
, const wchar_t *wcSrc
,
2383 BOOL truncate
= (count
== _TRUNCATE
);
2385 if(!wcDest
&& !numElement
&& !count
)
2388 if (!wcDest
|| !numElement
)
2394 return count
? EINVAL
: 0;
2397 while (numElement
&& count
&& *wcSrc
)
2403 if (!numElement
&& truncate
)
2408 else if (!numElement
)
2418 /******************************************************************
2419 * wcscat_s (MSVCRT.@)
2422 INT CDECL
wcscat_s(wchar_t* dst
, size_t elem
, const wchar_t* src
)
2426 if (!dst
|| elem
== 0) return EINVAL
;
2433 /* seek to end of dst string (or elem if no end of string is found */
2434 while (ptr
< dst
+ elem
&& *ptr
!= '\0') ptr
++;
2435 while (ptr
< dst
+ elem
)
2437 if ((*ptr
++ = *src
++) == '\0') return 0;
2439 /* not enough space */
2444 /***********************************************************************
2447 wchar_t* __cdecl
wcscat( wchar_t *dst
, const wchar_t *src
)
2449 wcscpy( dst
+ wcslen(dst
), src
);
2453 /*********************************************************************
2454 * wcsncat_s (MSVCRT.@)
2457 INT CDECL
wcsncat_s(wchar_t *dst
, size_t elem
,
2458 const wchar_t *src
, size_t count
)
2464 if (!MSVCRT_CHECK_PMT(dst
!= NULL
)) return EINVAL
;
2465 if (!MSVCRT_CHECK_PMT(elem
> 0)) return EINVAL
;
2466 if (!MSVCRT_CHECK_PMT(src
!= NULL
|| count
== 0)) return EINVAL
;
2471 for (dststart
= 0; dststart
< elem
; dststart
++)
2473 if (dst
[dststart
] == '\0')
2476 if (dststart
== elem
)
2478 MSVCRT_INVALID_PMT("dst[elem] is not NULL terminated\n", EINVAL
);
2482 if (count
== _TRUNCATE
)
2484 srclen
= wcslen(src
);
2485 if (srclen
>= (elem
- dststart
))
2487 srclen
= elem
- dststart
- 1;
2492 srclen
= min(wcslen(src
), count
);
2493 if (srclen
< (elem
- dststart
))
2495 memcpy(&dst
[dststart
], src
, srclen
*sizeof(wchar_t));
2496 dst
[dststart
+srclen
] = '\0';
2499 MSVCRT_INVALID_PMT("dst[elem] is too small", ERANGE
);
2504 /*********************************************************************
2507 wchar_t * __cdecl
wcsncat(wchar_t *s1
, const wchar_t *s2
, size_t n
)
2511 while (n
-- > 0) if (!(*s1
++ = *s2
++)) return ret
;
2516 /*********************************************************************
2517 * wctoint (INTERNAL)
2519 static int wctoint(WCHAR c
, int base
)
2522 if ('0' <= c
&& c
<= '9')
2524 else if ('A' <= c
&& c
<= 'Z')
2526 else if ('a' <= c
&& c
<= 'z')
2529 /* NOTE: wine_fold_string(MAP_FOLDDIGITS) supports too many things. */
2530 /* Unicode points that contain digits 0-9; keep this sorted! */
2531 static const WCHAR zeros
[] = {
2532 0x660, 0x6f0, 0x966, 0x9e6, 0xa66, 0xae6, 0xb66, 0xc66, 0xce6,
2533 0xd66, 0xe50, 0xed0, 0xf20, 0x1040, 0x17e0, 0x1810, 0xff10
2536 for (i
= 0; i
< ARRAY_SIZE(zeros
) && c
>= zeros
[i
]; ++i
) {
2537 if (zeros
[i
] <= c
&& c
<= zeros
[i
] + 9) {
2543 return v
< base
? v
: -1;
2546 /*********************************************************************
2547 * _wcstoi64_l (MSVCRT.@)
2549 __int64 CDECL
_wcstoi64_l(const wchar_t *nptr
,
2550 wchar_t **endptr
, int base
, _locale_t locale
)
2552 BOOL negative
= FALSE
, empty
= TRUE
;
2555 TRACE("(%s %p %d %p)\n", debugstr_w(nptr
), endptr
, base
, locale
);
2557 if (!MSVCRT_CHECK_PMT(nptr
!= NULL
)) return 0;
2558 if (!MSVCRT_CHECK_PMT(base
== 0 || base
>= 2)) return 0;
2559 if (!MSVCRT_CHECK_PMT(base
<= 36)) return 0;
2562 *endptr
= (wchar_t*)nptr
;
2564 while(_iswspace_l(*nptr
, locale
)) nptr
++;
2569 } else if(*nptr
== '+')
2572 if((base
==0 || base
==16) && wctoint(*nptr
, 1)==0 && (nptr
[1]=='x' || nptr
[1]=='X')) {
2578 if(wctoint(*nptr
, 1)==0)
2585 int v
= wctoint(*nptr
, base
);
2595 if(!negative
&& (ret
>I64_MAX
/base
|| ret
*base
>I64_MAX
-v
)) {
2598 } else if(negative
&& (ret
<I64_MIN
/base
|| ret
*base
<I64_MIN
-v
)) {
2605 if(endptr
&& !empty
)
2606 *endptr
= (wchar_t*)nptr
;
2611 /*********************************************************************
2612 * _wcstoi64 (MSVCRT.@)
2614 __int64 CDECL
_wcstoi64(const wchar_t *nptr
,
2615 wchar_t **endptr
, int base
)
2617 return _wcstoi64_l(nptr
, endptr
, base
, NULL
);
2620 /*********************************************************************
2621 * _wcstol_l (MSVCRT.@)
2623 __msvcrt_long CDECL
_wcstol_l(const wchar_t *s
,
2624 wchar_t **end
, int base
, _locale_t locale
)
2626 __int64 ret
= _wcstoi64_l(s
, end
, base
, locale
);
2628 if(ret
> LONG_MAX
) {
2631 }else if(ret
< LONG_MIN
) {
2638 /*********************************************************************
2641 __msvcrt_long CDECL
wcstol(const wchar_t *s
,
2642 wchar_t **end
, int base
)
2644 return _wcstol_l(s
, end
, base
, NULL
);
2647 /*********************************************************************
2648 * _wtoi_l (MSVCRT.@)
2650 int __cdecl
_wtoi_l(const wchar_t *str
, _locale_t locale
)
2652 __int64 ret
= _wcstoi64_l(str
, NULL
, 10, locale
);
2657 } else if(ret
< INT_MIN
) {
2664 /*********************************************************************
2667 int __cdecl
_wtoi(const wchar_t *str
)
2669 return _wtoi_l(str
, NULL
);
2672 /*********************************************************************
2673 * _wtol_l (MSVCRT.@)
2675 __msvcrt_long __cdecl
_wtol_l(const wchar_t *str
, _locale_t locale
)
2677 __int64 ret
= _wcstoi64_l(str
, NULL
, 10, locale
);
2679 if(ret
> LONG_MAX
) {
2682 } else if(ret
< LONG_MIN
) {
2689 /*********************************************************************
2692 __msvcrt_long __cdecl
_wtol(const wchar_t *str
)
2694 return _wtol_l(str
, NULL
);
2699 /*********************************************************************
2700 * _wtoll_l (MSVCR120.@)
2702 __int64 __cdecl
_wtoll_l(const wchar_t *str
, _locale_t locale
)
2704 return _wcstoi64_l(str
, NULL
, 10, locale
);
2707 /*********************************************************************
2708 * _wtoll (MSVCR120.@)
2710 __int64 __cdecl
_wtoll(const wchar_t *str
)
2712 return _wtoll_l(str
, NULL
);
2715 #endif /* _MSVCR_VER>=120 */
2717 /*********************************************************************
2718 * _wcstoui64_l (MSVCRT.@)
2720 unsigned __int64 CDECL
_wcstoui64_l(const wchar_t *nptr
,
2721 wchar_t **endptr
, int base
, _locale_t locale
)
2723 BOOL negative
= FALSE
, empty
= TRUE
;
2724 unsigned __int64 ret
= 0;
2726 TRACE("(%s %p %d %p)\n", debugstr_w(nptr
), endptr
, base
, locale
);
2728 if (!MSVCRT_CHECK_PMT(nptr
!= NULL
)) return 0;
2729 if (!MSVCRT_CHECK_PMT(base
== 0 || base
>= 2)) return 0;
2730 if (!MSVCRT_CHECK_PMT(base
<= 36)) return 0;
2733 *endptr
= (wchar_t*)nptr
;
2735 while(_iswspace_l(*nptr
, locale
)) nptr
++;
2740 } else if(*nptr
== '+')
2743 if((base
==0 || base
==16) && wctoint(*nptr
, 1)==0 && (nptr
[1]=='x' || nptr
[1]=='X')) {
2749 if(wctoint(*nptr
, 1)==0)
2756 int v
= wctoint(*nptr
, base
);
2763 if(ret
>UI64_MAX
/base
|| ret
*base
>UI64_MAX
-v
) {
2770 if(endptr
&& !empty
)
2771 *endptr
= (wchar_t*)nptr
;
2773 return negative
? -ret
: ret
;
2776 /*********************************************************************
2777 * _wcstoui64 (MSVCRT.@)
2779 unsigned __int64 CDECL
_wcstoui64(const wchar_t *nptr
,
2780 wchar_t **endptr
, int base
)
2782 return _wcstoui64_l(nptr
, endptr
, base
, NULL
);
2785 /*********************************************************************
2786 * _wcstoul_l (MSVCRT.@)
2788 __msvcrt_ulong __cdecl
_wcstoul_l(const wchar_t *s
,
2789 wchar_t **end
, int base
, _locale_t locale
)
2791 __int64 ret
= _wcstoi64_l(s
, end
, base
, locale
);
2793 if(ret
> ULONG_MAX
) {
2796 }else if(ret
< -(__int64
)ULONG_MAX
) {
2803 /*********************************************************************
2804 * wcstoul (MSVCRT.@)
2806 __msvcrt_ulong __cdecl
wcstoul(const wchar_t *s
, wchar_t **end
, int base
)
2808 return _wcstoul_l(s
, end
, base
, NULL
);
2811 /******************************************************************
2812 * wcsnlen (MSVCRT.@)
2814 size_t CDECL
wcsnlen(const wchar_t *s
, size_t maxlen
)
2818 for (i
= 0; i
< maxlen
; i
++)
2823 /*********************************************************************
2824 * _towupper_l (MSVCRT.@)
2826 wint_t CDECL
_towupper_l(wint_t c
, _locale_t locale
)
2828 pthreadlocinfo locinfo
;
2832 locinfo
= get_locinfo();
2834 locinfo
= locale
->locinfo
;
2836 if(!locinfo
->lc_handle
[LC_CTYPE
]) {
2837 if(c
>= 'a' && c
<= 'z')
2838 return c
+ 'A' - 'a';
2842 if(!LCMapStringW(locinfo
->lc_handle
[LC_CTYPE
], LCMAP_UPPERCASE
, &c
, 1, &ret
, 1))
2847 /*********************************************************************
2848 * towupper (MSVCRT.@)
2850 wint_t CDECL
towupper(wint_t c
)
2852 return _towupper_l(c
, NULL
);
2855 /*********************************************************************
2858 wchar_t* CDECL
wcschr(const wchar_t *str
, wchar_t ch
)
2860 do { if (*str
== ch
) return (WCHAR
*)(ULONG_PTR
)str
; } while (*str
++);
2864 /*********************************************************************
2865 * wcsrchr (MSVCRT.@)
2867 wchar_t* CDECL
wcsrchr(const wchar_t *str
, wchar_t ch
)
2870 do { if (*str
== ch
) ret
= (WCHAR
*)(ULONG_PTR
)str
; } while (*str
++);
2874 /***********************************************************************
2877 size_t CDECL
wcslen(const wchar_t *str
)
2879 const wchar_t *s
= str
;
2884 /*********************************************************************
2887 wchar_t* CDECL
wcsstr(const wchar_t *str
, const wchar_t *sub
)
2891 const wchar_t *p1
= str
, *p2
= sub
;
2892 while(*p1
&& *p2
&& *p1
== *p2
)
2898 return (wchar_t*)str
;
2904 /*********************************************************************
2905 * _wtoi64_l (MSVCRT.@)
2907 __int64 CDECL
_wtoi64_l(const wchar_t *str
, _locale_t locale
)
2909 ULONGLONG RunningTotal
= 0;
2910 BOOL bMinus
= FALSE
;
2912 while (_iswspace_l(*str
, locale
)) {
2918 } else if (*str
== '-') {
2923 while (*str
>= '0' && *str
<= '9') {
2924 RunningTotal
= RunningTotal
* 10 + *str
- '0';
2928 return bMinus
? -RunningTotal
: RunningTotal
;
2931 /*********************************************************************
2932 * _wtoi64 (MSVCRT.@)
2934 __int64 CDECL
_wtoi64(const wchar_t *str
)
2936 return _wtoi64_l(str
, NULL
);
2939 /*********************************************************************
2940 * _wcsxfrm_l (MSVCRT.@)
2942 size_t CDECL
_wcsxfrm_l(wchar_t *dest
, const wchar_t *src
,
2943 size_t len
, _locale_t locale
)
2945 pthreadlocinfo locinfo
;
2948 if(!MSVCRT_CHECK_PMT(src
)) return INT_MAX
;
2949 if(!MSVCRT_CHECK_PMT(dest
|| !len
)) return INT_MAX
;
2952 FIXME("len > INT_MAX not supported\n");
2957 locinfo
= get_locinfo();
2959 locinfo
= locale
->locinfo
;
2961 if(!locinfo
->lc_handle
[LC_COLLATE
]) {
2962 wcsncpy(dest
, src
, len
);
2966 ret
= LCMapStringW(locinfo
->lc_handle
[LC_COLLATE
],
2967 LCMAP_SORTKEY
, src
, -1, NULL
, 0);
2969 if(len
) dest
[0] = 0;
2973 if(!len
) return ret
-1;
2981 ret
= LCMapStringW(locinfo
->lc_handle
[LC_COLLATE
],
2982 LCMAP_SORTKEY
, src
, -1, dest
, len
) - 1;
2983 for(i
=ret
; i
>=0; i
--)
2984 dest
[i
] = ((unsigned char*)dest
)[i
];
2988 /*********************************************************************
2989 * wcsxfrm (MSVCRT.@)
2991 size_t CDECL
wcsxfrm(wchar_t *dest
, const wchar_t *src
, size_t len
)
2993 return _wcsxfrm_l(dest
, src
, len
, NULL
);