msvcrt: Remove MSVCRT_lconv type.
[wine.git] / dlls / msvcrt / wcs.c
blob0f4e72ac0f5cfe1abd8c63a4f7f9430e02b644b3
1 /*
2 * msvcrt.dll wide-char functions
4 * Copyright 1999 Alexandre Julliard
5 * Copyright 2000 Jon Griffiths
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <limits.h>
23 #include <locale.h>
24 #include <stdio.h>
25 #include <math.h>
26 #include <assert.h>
27 #include <wctype.h>
28 #include "msvcrt.h"
29 #include "winnls.h"
30 #include "wtypes.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
35 typedef struct
37 enum { LEN_DEFAULT, LEN_SHORT, LEN_LONG } IntegerLength;
38 BOOLEAN IntegerDouble, IntegerNative, LeftAlign, Alternate, PadZero;
39 BOOLEAN WideString, NaturalString;
40 int FieldLength, Precision;
41 char Sign, Format;
42 } pf_flags;
44 static BOOL n_format_enabled = TRUE;
46 #include "printf.h"
47 #define PRINTF_WIDE
48 #include "printf.h"
49 #undef PRINTF_WIDE
51 #if _MSVCR_VER>=80
53 /*********************************************************************
54 * _get_printf_count_output (MSVCR80.@)
56 int CDECL MSVCRT__get_printf_count_output( void )
58 return n_format_enabled ? 1 : 0;
61 /*********************************************************************
62 * _set_printf_count_output (MSVCR80.@)
64 int CDECL MSVCRT__set_printf_count_output( int enable )
66 BOOL old = n_format_enabled;
67 n_format_enabled = enable != 0;
68 return old ? 1 : 0;
71 #endif /* _MSVCR_VER>=80 */
73 /*********************************************************************
74 * _wcsdup (MSVCRT.@)
76 MSVCRT_wchar_t* CDECL MSVCRT__wcsdup( const MSVCRT_wchar_t* str )
78 MSVCRT_wchar_t* ret = NULL;
79 if (str)
81 int size = (MSVCRT_wcslen(str) + 1) * sizeof(MSVCRT_wchar_t);
82 ret = MSVCRT_malloc( size );
83 if (ret) memcpy( ret, str, size );
85 return ret;
88 /*********************************************************************
89 * _towlower_l (MSVCRT.@)
91 int CDECL MSVCRT__towlower_l(MSVCRT_wint_t c, MSVCRT__locale_t locale)
93 MSVCRT_pthreadlocinfo locinfo;
94 MSVCRT_wchar_t ret;
96 if(!locale)
97 locinfo = get_locinfo();
98 else
99 locinfo = locale->locinfo;
101 if(!locinfo->lc_handle[MSVCRT_LC_CTYPE]) {
102 if(c >= 'A' && c <= 'Z')
103 return c + 'a' - 'A';
104 return c;
107 if(!LCMapStringW(locinfo->lc_handle[MSVCRT_LC_CTYPE], LCMAP_LOWERCASE, &c, 1, &ret, 1))
108 return c;
109 return ret;
112 /*********************************************************************
113 * towlower (MSVCRT.@)
115 int CDECL MSVCRT_towlower(MSVCRT_wint_t c)
117 return MSVCRT__towlower_l(c, NULL);
120 INT CDECL MSVCRT__wcsicmp_l(const MSVCRT_wchar_t *str1, const MSVCRT_wchar_t *str2, MSVCRT__locale_t locale)
122 MSVCRT__locale_tstruct tmp = {0};
123 MSVCRT_wchar_t c1, c2;
125 if(!MSVCRT_CHECK_PMT(str1 != NULL) || !MSVCRT_CHECK_PMT(str2 != NULL))
126 return MSVCRT__NLSCMPERROR;
128 if(!locale)
129 locale = get_current_locale_noalloc(&tmp);
133 c1 = MSVCRT__towlower_l(*str1++, locale);
134 c2 = MSVCRT__towlower_l(*str2++, locale);
135 } while(c1 && (c1 == c2));
137 free_locale_noalloc(&tmp);
138 return c1 - c2;
141 /*********************************************************************
142 * towctrans (MSVCR120.@)
144 wint_t CDECL towctrans(wint_t c, wctrans_t category)
146 if(category == 1)
147 return MSVCRT__towupper_l(c, NULL);
148 return MSVCRT__towlower_l(c, NULL);
151 /*********************************************************************
152 * _wcsicmp (MSVCRT.@)
154 INT CDECL MSVCRT__wcsicmp( const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2 )
156 return MSVCRT__wcsicmp_l(str1, str2, NULL);
159 /*********************************************************************
160 * _wcsnicmp_l (MSVCRT.@)
162 INT CDECL MSVCRT__wcsnicmp_l(const MSVCRT_wchar_t *str1, const MSVCRT_wchar_t *str2,
163 MSVCRT_size_t n, MSVCRT__locale_t locale)
165 MSVCRT__locale_tstruct tmp = {0};
166 MSVCRT_wchar_t c1, c2;
168 if (!n)
169 return 0;
171 if(!MSVCRT_CHECK_PMT(str1 != NULL) || !MSVCRT_CHECK_PMT(str2 != NULL))
172 return MSVCRT__NLSCMPERROR;
174 if(!locale)
175 locale = get_current_locale_noalloc(&tmp);
179 c1 = MSVCRT__towlower_l(*str1++, locale);
180 c2 = MSVCRT__towlower_l(*str2++, locale);
181 } while(--n && c1 && (c1 == c2));
183 free_locale_noalloc(&tmp);
184 return c1 - c2;
187 /*********************************************************************
188 * _wcsnicmp (MSVCRT.@)
190 INT CDECL MSVCRT__wcsnicmp(const MSVCRT_wchar_t *str1, const MSVCRT_wchar_t *str2, MSVCRT_size_t n)
192 return MSVCRT__wcsnicmp_l(str1, str2, n, NULL);
195 /*********************************************************************
196 * _wcsicoll_l (MSVCRT.@)
198 int CDECL MSVCRT__wcsicoll_l(const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2, MSVCRT__locale_t locale)
200 MSVCRT_pthreadlocinfo locinfo;
202 if(!locale)
203 locinfo = get_locinfo();
204 else
205 locinfo = locale->locinfo;
207 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE])
209 MSVCRT_wchar_t c1, c2;
213 c1 = *str1++;
214 if (c1 >= 'A' && c1 <= 'Z')
215 c1 += 'a' - 'A';
217 c2 = *str2++;
218 if (c2 >= 'A' && c2 <= 'Z')
219 c2 += 'a' - 'A';
220 } while(c1 && (c1 == c2));
221 return c1 - c2;
224 return CompareStringW(locinfo->lc_handle[MSVCRT_LC_COLLATE], NORM_IGNORECASE,
225 str1, -1, str2, -1)-CSTR_EQUAL;
228 /*********************************************************************
229 * _wcsicoll (MSVCRT.@)
231 INT CDECL MSVCRT__wcsicoll( const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2 )
233 return MSVCRT__wcsicoll_l(str1, str2, NULL);
236 /*********************************************************************
237 * _wcsnicoll_l (MSVCRT.@)
239 int CDECL MSVCRT__wcsnicoll_l(const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2,
240 MSVCRT_size_t count, MSVCRT__locale_t locale)
242 MSVCRT_pthreadlocinfo locinfo;
244 if(!locale)
245 locinfo = get_locinfo();
246 else
247 locinfo = locale->locinfo;
249 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE])
251 MSVCRT_wchar_t c1, c2;
253 if (!count)
254 return 0;
258 c1 = *str1++;
259 if (c1 >= 'A' && c1 <= 'Z')
260 c1 += 'a' - 'A';
262 c2 = *str2++;
263 if (c2 >= 'A' && c2 <= 'Z')
264 c2 += 'a' - 'A';
265 } while(--count && c1 && (c1 == c2));
266 return c1 - c2;
269 return CompareStringW(locinfo->lc_handle[MSVCRT_LC_COLLATE], NORM_IGNORECASE,
270 str1, MSVCRT_wcsnlen(str1, count),
271 str2, MSVCRT_wcsnlen(str2, count))-CSTR_EQUAL;
274 /*********************************************************************
275 * _wcsnicoll (MSVCRT.@)
277 INT CDECL MSVCRT__wcsnicoll( const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2, MSVCRT_size_t count )
279 return MSVCRT__wcsnicoll_l(str1, str2, count, NULL);
282 /*********************************************************************
283 * _wcsnset (MSVCRT.@)
285 MSVCRT_wchar_t* CDECL MSVCRT__wcsnset( MSVCRT_wchar_t* str, MSVCRT_wchar_t c, MSVCRT_size_t n )
287 MSVCRT_wchar_t* ret = str;
288 while ((n-- > 0) && *str) *str++ = c;
289 return ret;
292 /*********************************************************************
293 * _wcsnset_s (MSVCRT.@)
295 int CDECL MSVCRT__wcsnset_s( MSVCRT_wchar_t *str, MSVCRT_size_t size, MSVCRT_wchar_t c, MSVCRT_size_t count )
297 MSVCRT_size_t i;
299 if(!str && !size && !count) return 0;
300 if(!MSVCRT_CHECK_PMT(str != NULL)) return MSVCRT_EINVAL;
301 if(!MSVCRT_CHECK_PMT(size > 0)) return MSVCRT_EINVAL;
303 for(i=0; i<size-1 && i<count; i++) {
304 if(!str[i]) return 0;
305 str[i] = c;
307 for(; i<size; i++)
308 if(!str[i]) return 0;
310 str[0] = 0;
311 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
312 *MSVCRT__errno() = MSVCRT_EINVAL;
313 return MSVCRT_EINVAL;
316 /*********************************************************************
317 * _wcsrev (MSVCRT.@)
319 MSVCRT_wchar_t* CDECL MSVCRT__wcsrev( MSVCRT_wchar_t* str )
321 MSVCRT_wchar_t* ret = str;
322 MSVCRT_wchar_t* end = str + MSVCRT_wcslen(str) - 1;
323 while (end > str)
325 MSVCRT_wchar_t t = *end;
326 *end-- = *str;
327 *str++ = t;
329 return ret;
332 /*********************************************************************
333 * _wcsset_s (MSVCRT.@)
335 int CDECL MSVCRT__wcsset_s( MSVCRT_wchar_t *str, MSVCRT_size_t n, MSVCRT_wchar_t c )
337 MSVCRT_wchar_t *p = str;
339 if(!MSVCRT_CHECK_PMT(str != NULL)) return MSVCRT_EINVAL;
340 if(!MSVCRT_CHECK_PMT(n)) return MSVCRT_EINVAL;
342 while(*p && --n) *p++ = c;
343 if(!n) {
344 str[0] = 0;
345 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
346 *MSVCRT__errno() = MSVCRT_EINVAL;
347 return MSVCRT_EINVAL;
349 return 0;
352 /*********************************************************************
353 * _wcsset (MSVCRT.@)
355 MSVCRT_wchar_t* CDECL MSVCRT__wcsset( MSVCRT_wchar_t* str, MSVCRT_wchar_t c )
357 MSVCRT_wchar_t* ret = str;
358 while (*str) *str++ = c;
359 return ret;
362 /******************************************************************
363 * _wcsupr_s_l (MSVCRT.@)
365 int CDECL MSVCRT__wcsupr_s_l( MSVCRT_wchar_t* str, MSVCRT_size_t n,
366 MSVCRT__locale_t locale )
368 MSVCRT__locale_tstruct tmp = {0};
369 MSVCRT_wchar_t* ptr = str;
371 if (!str || !n)
373 if (str) *str = '\0';
374 *MSVCRT__errno() = MSVCRT_EINVAL;
375 return MSVCRT_EINVAL;
378 if(!locale)
379 locale = get_current_locale_noalloc(&tmp);
381 while (n--)
383 if (!*ptr)
385 free_locale_noalloc(&tmp);
386 return 0;
388 *ptr = MSVCRT__towupper_l(*ptr, locale);
389 ptr++;
392 free_locale_noalloc(&tmp);
394 /* MSDN claims that the function should return and set errno to
395 * ERANGE, which doesn't seem to be true based on the tests. */
396 *str = '\0';
397 *MSVCRT__errno() = MSVCRT_EINVAL;
398 return MSVCRT_EINVAL;
401 /******************************************************************
402 * _wcsupr_s (MSVCRT.@)
405 INT CDECL MSVCRT__wcsupr_s( MSVCRT_wchar_t* str, MSVCRT_size_t n )
407 return MSVCRT__wcsupr_s_l( str, n, NULL );
410 /******************************************************************
411 * _wcsupr_l (MSVCRT.@)
413 MSVCRT_wchar_t* CDECL MSVCRT__wcsupr_l( MSVCRT_wchar_t *str, MSVCRT__locale_t locale )
415 MSVCRT__wcsupr_s_l( str, -1, locale);
416 return str;
419 /******************************************************************
420 * _wcsupr (MSVCRT.@)
422 MSVCRT_wchar_t* CDECL MSVCRT__wcsupr( MSVCRT_wchar_t *str )
424 return MSVCRT__wcsupr_l(str, NULL);
427 /******************************************************************
428 * _wcslwr_s_l (MSVCRT.@)
430 int CDECL MSVCRT__wcslwr_s_l( MSVCRT_wchar_t* str, MSVCRT_size_t n, MSVCRT__locale_t locale )
432 MSVCRT__locale_tstruct tmp = {0};
433 MSVCRT_wchar_t* ptr = str;
435 if (!str || !n)
437 if (str) *str = '\0';
438 *MSVCRT__errno() = MSVCRT_EINVAL;
439 return MSVCRT_EINVAL;
442 if(!locale)
443 locale = get_current_locale_noalloc(&tmp);
445 while (n--)
447 if (!*ptr)
449 free_locale_noalloc(&tmp);
450 return 0;
452 *ptr = MSVCRT__towlower_l(*ptr, locale);
453 ptr++;
456 free_locale_noalloc(&tmp);
458 /* MSDN claims that the function should return and set errno to
459 * ERANGE, which doesn't seem to be true based on the tests. */
460 *str = '\0';
461 *MSVCRT__errno() = MSVCRT_EINVAL;
462 return MSVCRT_EINVAL;
465 /******************************************************************
466 * _wcslwr_s (MSVCRT.@)
468 int CDECL MSVCRT__wcslwr_s( MSVCRT_wchar_t* str, MSVCRT_size_t n )
470 return MSVCRT__wcslwr_s_l(str, n, NULL);
473 /******************************************************************
474 * _wcslwr_l (MSVCRT.@)
476 MSVCRT_wchar_t* CDECL MSVCRT__wcslwr_l( MSVCRT_wchar_t* str, MSVCRT__locale_t locale )
478 MSVCRT__wcslwr_s_l(str, -1, locale);
479 return str;
482 /******************************************************************
483 * _wcslwr (MSVCRT.@)
485 MSVCRT_wchar_t* CDECL MSVCRT__wcslwr( MSVCRT_wchar_t* str )
487 MSVCRT__wcslwr_s_l(str, -1, NULL);
488 return str;
491 /*********************************************************************
492 * wcsncmp (MSVCRT.@)
494 int CDECL MSVCRT_wcsncmp(const MSVCRT_wchar_t *str1, const MSVCRT_wchar_t *str2, MSVCRT_size_t n)
496 if (!n)
497 return 0;
498 while(--n && *str1 && (*str1 == *str2))
500 str1++;
501 str2++;
503 return *str1 - *str2;
506 /*********************************************************************
507 * _wcsncoll_l (MSVCRT.@)
509 int CDECL MSVCRT__wcsncoll_l(const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2,
510 MSVCRT_size_t count, MSVCRT__locale_t locale)
512 MSVCRT_pthreadlocinfo locinfo;
514 if(!locale)
515 locinfo = get_locinfo();
516 else
517 locinfo = locale->locinfo;
519 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE])
520 return MSVCRT_wcsncmp(str1, str2, count);
521 return CompareStringW(locinfo->lc_handle[MSVCRT_LC_COLLATE], 0,
522 str1, MSVCRT_wcsnlen(str1, count),
523 str2, MSVCRT_wcsnlen(str2, count))-CSTR_EQUAL;
526 /*********************************************************************
527 * _wcsncoll (MSVCRT.@)
529 int CDECL MSVCRT__wcsncoll(const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2, MSVCRT_size_t count)
531 return MSVCRT__wcsncoll_l(str1, str2, count, NULL);
534 static MSVCRT_wchar_t strtod_wstr_get(void *ctx)
536 const MSVCRT_wchar_t **p = ctx;
537 if (!**p) return MSVCRT_WEOF;
538 return *(*p)++;
541 static void strtod_wstr_unget(void *ctx)
543 const MSVCRT_wchar_t **p = ctx;
544 (*p)--;
547 /*********************************************************************
548 * _wcstod_l (MSVCRT.@)
550 double CDECL MSVCRT__wcstod_l(const MSVCRT_wchar_t* str, MSVCRT_wchar_t** end,
551 MSVCRT__locale_t locale)
553 MSVCRT_pthreadlocinfo locinfo;
554 const MSVCRT_wchar_t *beg, *p;
555 struct fpnum fp;
556 double ret;
557 int err;
559 if (!MSVCRT_CHECK_PMT(str != NULL)) {
560 if (end) *end = NULL;
561 return 0;
564 if (!locale)
565 locinfo = get_locinfo();
566 else
567 locinfo = locale->locinfo;
569 p = str;
570 while(MSVCRT__iswspace_l(*p, locale))
571 p++;
572 beg = p;
574 fp = fpnum_parse(strtod_wstr_get, strtod_wstr_unget, &p, locinfo, FALSE);
575 if (end) *end = (p == beg ? (MSVCRT_wchar_t*)str : (MSVCRT_wchar_t*)p);
577 err = fpnum_double(&fp, &ret);
578 if(err) *MSVCRT__errno() = err;
579 return ret;
582 /*********************************************************************
583 * wcsrtombs_l (INTERNAL)
585 static MSVCRT_size_t MSVCRT_wcsrtombs_l(char *mbstr, const MSVCRT_wchar_t **wcstr,
586 MSVCRT_size_t count, MSVCRT__locale_t locale)
588 MSVCRT_pthreadlocinfo locinfo;
589 MSVCRT_size_t tmp = 0;
590 BOOL used_default = FALSE;
591 BOOL *pused_default;
593 if(!locale)
594 locinfo = get_locinfo();
595 else
596 locinfo = locale->locinfo;
598 if(!locinfo->lc_codepage) {
599 MSVCRT_size_t i;
601 if(!mbstr)
602 return MSVCRT_wcslen(*wcstr);
604 for(i=0; i<count; i++) {
605 if((*wcstr)[i] > 255) {
606 *MSVCRT__errno() = MSVCRT_EILSEQ;
607 return -1;
610 mbstr[i] = (*wcstr)[i];
611 if(!(*wcstr)[i]) break;
613 return i;
616 pused_default = (locinfo->lc_codepage != CP_UTF8 ? &used_default : NULL);
618 if(!mbstr) {
619 tmp = WideCharToMultiByte(locinfo->lc_codepage, WC_NO_BEST_FIT_CHARS,
620 *wcstr, -1, NULL, 0, NULL, pused_default);
621 if(!tmp || used_default) {
622 *MSVCRT__errno() = MSVCRT_EILSEQ;
623 return -1;
625 return tmp-1;
628 while(**wcstr) {
629 char buf[3];
630 MSVCRT_size_t i, size;
632 size = WideCharToMultiByte(locinfo->lc_codepage, WC_NO_BEST_FIT_CHARS,
633 *wcstr, 1, buf, 3, NULL, pused_default);
634 if(!size || used_default) {
635 *MSVCRT__errno() = MSVCRT_EILSEQ;
636 return -1;
638 if(tmp+size > count)
639 return tmp;
641 for(i=0; i<size; i++)
642 mbstr[tmp++] = buf[i];
643 (*wcstr)++;
646 if(tmp < count) {
647 mbstr[tmp] = '\0';
648 *wcstr = NULL;
650 return tmp;
653 /*********************************************************************
654 * _wcstombs_l (MSVCRT.@)
656 MSVCRT_size_t CDECL MSVCRT__wcstombs_l(char *mbstr, const MSVCRT_wchar_t *wcstr,
657 MSVCRT_size_t count, MSVCRT__locale_t locale)
659 return MSVCRT_wcsrtombs_l(mbstr, &wcstr, count, locale);
662 /*********************************************************************
663 * wcstombs (MSVCRT.@)
665 MSVCRT_size_t CDECL MSVCRT_wcstombs(char *mbstr, const MSVCRT_wchar_t *wcstr,
666 MSVCRT_size_t count)
668 return MSVCRT_wcsrtombs_l(mbstr, &wcstr, count, NULL);
671 /*********************************************************************
672 * wcsrtombs (MSVCRT.@)
674 MSVCRT_size_t CDECL MSVCRT_wcsrtombs(char *mbstr, const MSVCRT_wchar_t **wcstr,
675 MSVCRT_size_t count, MSVCRT_mbstate_t *mbstate)
677 if(mbstate)
678 *mbstate = 0;
680 return MSVCRT_wcsrtombs_l(mbstr, wcstr, count, NULL);
683 /*********************************************************************
684 * MSVCRT_wcsrtombs_s_l (INTERNAL)
686 static int MSVCRT_wcsrtombs_s_l(MSVCRT_size_t *ret, char *mbstr,
687 MSVCRT_size_t size, const MSVCRT_wchar_t **wcstr,
688 MSVCRT_size_t count, MSVCRT__locale_t locale)
690 MSVCRT_size_t conv;
691 int err;
693 if(!mbstr && !size && wcstr) {
694 conv = MSVCRT_wcsrtombs_l(NULL, wcstr, 0, locale);
695 if(ret)
696 *ret = conv+1;
697 if(conv == -1)
698 return *MSVCRT__errno();
699 return 0;
702 if (!MSVCRT_CHECK_PMT(mbstr != NULL)) return MSVCRT_EINVAL;
703 if (size) mbstr[0] = '\0';
704 if (!MSVCRT_CHECK_PMT(wcstr != NULL)) return MSVCRT_EINVAL;
705 if (!MSVCRT_CHECK_PMT(*wcstr != NULL)) return MSVCRT_EINVAL;
707 if(count==MSVCRT__TRUNCATE || size<count)
708 conv = size;
709 else
710 conv = count;
712 err = 0;
713 conv = MSVCRT_wcsrtombs_l(mbstr, wcstr, conv, locale);
714 if(conv == -1) {
715 conv = 0;
716 if(size)
717 mbstr[0] = '\0';
718 err = *MSVCRT__errno();
719 }else if(conv < size)
720 mbstr[conv++] = '\0';
721 else if(conv==size && (count==MSVCRT__TRUNCATE || mbstr[conv-1]=='\0')) {
722 mbstr[conv-1] = '\0';
723 if(count==MSVCRT__TRUNCATE)
724 err = MSVCRT_STRUNCATE;
725 }else {
726 MSVCRT_INVALID_PMT("mbstr[size] is too small", MSVCRT_ERANGE);
727 conv = 0;
728 if(size)
729 mbstr[0] = '\0';
730 err = MSVCRT_ERANGE;
733 if(ret)
734 *ret = conv;
735 return err;
738 /*********************************************************************
739 * _wcstombs_s_l (MSVCRT.@)
741 int CDECL MSVCRT__wcstombs_s_l(MSVCRT_size_t *ret, char *mbstr,
742 MSVCRT_size_t size, const MSVCRT_wchar_t *wcstr,
743 MSVCRT_size_t count, MSVCRT__locale_t locale)
745 return MSVCRT_wcsrtombs_s_l(ret, mbstr, size, &wcstr,count, locale);
748 /*********************************************************************
749 * wcstombs_s (MSVCRT.@)
751 int CDECL MSVCRT_wcstombs_s(MSVCRT_size_t *ret, char *mbstr,
752 MSVCRT_size_t size, const MSVCRT_wchar_t *wcstr, MSVCRT_size_t count)
754 return MSVCRT_wcsrtombs_s_l(ret, mbstr, size, &wcstr, count, NULL);
757 /*********************************************************************
758 * wcsrtombs_s (MSVCRT.@)
760 int CDECL MSVCRT_wcsrtombs_s(MSVCRT_size_t *ret, char *mbstr, MSVCRT_size_t size,
761 const MSVCRT_wchar_t **wcstr, MSVCRT_size_t count, MSVCRT_mbstate_t *mbstate)
763 if(mbstate)
764 *mbstate = 0;
766 return MSVCRT_wcsrtombs_s_l(ret, mbstr, size, wcstr, count, NULL);
769 /*********************************************************************
770 * wcstod (MSVCRT.@)
772 double CDECL MSVCRT_wcstod(const MSVCRT_wchar_t* lpszStr, MSVCRT_wchar_t** end)
774 return MSVCRT__wcstod_l(lpszStr, end, NULL);
777 /*********************************************************************
778 * _wtof (MSVCRT.@)
780 double CDECL MSVCRT__wtof(const MSVCRT_wchar_t *str)
782 return MSVCRT__wcstod_l(str, NULL, NULL);
785 /*********************************************************************
786 * _wtof_l (MSVCRT.@)
788 double CDECL MSVCRT__wtof_l(const MSVCRT_wchar_t *str, MSVCRT__locale_t locale)
790 return MSVCRT__wcstod_l(str, NULL, locale);
793 #if _MSVCR_VER>=120
795 /*********************************************************************
796 * _wcstof_l (MSVCR120.@)
798 float CDECL MSVCRT__wcstof_l( const MSVCRT_wchar_t *str, MSVCRT_wchar_t **end, MSVCRT__locale_t locale )
800 return MSVCRT__wcstod_l(str, end, locale);
803 /*********************************************************************
804 * wcstof (MSVCR120.@)
806 float CDECL MSVCRT_wcstof( const MSVCRT_wchar_t *str, MSVCRT_wchar_t **end )
808 return MSVCRT__wcstof_l(str, end, NULL);
811 #endif /* _MSVCR_VER>=120 */
813 /*********************************************************************
814 * arg_clbk_valist (INTERNAL)
816 printf_arg arg_clbk_valist(void *ctx, int arg_pos, int type, __ms_va_list *valist)
818 printf_arg ret;
820 if(type == VT_I8)
821 ret.get_longlong = va_arg(*valist, LONGLONG);
822 else if(type == VT_INT)
823 ret.get_int = va_arg(*valist, int);
824 else if(type == VT_R8)
825 ret.get_double = va_arg(*valist, double);
826 else if(type == VT_PTR)
827 ret.get_ptr = va_arg(*valist, void*);
828 else {
829 ERR("Incorrect type\n");
830 ret.get_int = 0;
833 return ret;
836 /*********************************************************************
837 * arg_clbk_positional (INTERNAL)
839 printf_arg arg_clbk_positional(void *ctx, int pos, int type, __ms_va_list *valist)
841 printf_arg *args = ctx;
842 return args[pos];
845 #if _MSVCR_VER < 140
847 /*********************************************************************
848 * _vsnprintf (MSVCRT.@)
850 int CDECL _vsnprintf( char *str, size_t len, const char *format, __ms_va_list valist )
852 static const char nullbyte = '\0';
853 struct _str_ctx_a ctx = {len, str};
854 int ret;
856 ret = pf_printf_a(puts_clbk_str_a, &ctx, format, NULL, 0,
857 arg_clbk_valist, NULL, &valist);
858 puts_clbk_str_a(&ctx, 1, &nullbyte);
859 return ret;
862 #else
864 static int puts_clbk_str_c99_a(void *ctx, int len, const char *str)
866 struct _str_ctx_a *out = ctx;
868 if(!out->buf)
869 return len;
871 if(out->len < len) {
872 memmove(out->buf, str, out->len);
873 out->buf += out->len;
874 out->len = 0;
875 return len;
878 memmove(out->buf, str, len);
879 out->buf += len;
880 out->len -= len;
881 return len;
884 /*********************************************************************
885 * __stdio_common_vsprintf (UCRTBASE.@)
887 int CDECL __stdio_common_vsprintf( unsigned __int64 options, char *str, size_t len, const char *format,
888 _locale_t locale, __ms_va_list valist )
890 static const char nullbyte = '\0';
891 struct _str_ctx_a ctx = {len, str};
892 int ret;
894 if (options & ~UCRTBASE_PRINTF_MASK)
895 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
896 ret = pf_printf_a(puts_clbk_str_c99_a,
897 &ctx, format, (MSVCRT__locale_t)locale, options & UCRTBASE_PRINTF_MASK, arg_clbk_valist, NULL, &valist);
898 puts_clbk_str_a(&ctx, 1, &nullbyte);
900 if(!str)
901 return ret;
902 if(options & UCRTBASE_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION)
903 return ret>len ? -1 : ret;
904 if(ret>=len) {
905 if(len) str[len-1] = 0;
906 if(options & UCRTBASE_PRINTF_STANDARD_SNPRINTF_BEHAVIOUR)
907 return ret;
908 return len > 0 ? -2 : -1;
910 return ret;
913 #endif /* _MSVCR_VER>=140 */
915 /*********************************************************************
916 * _vsnprintf_l (MSVCRT.@)
918 int CDECL MSVCRT_vsnprintf_l( char *str, MSVCRT_size_t len, const char *format,
919 MSVCRT__locale_t locale, __ms_va_list valist )
921 static const char nullbyte = '\0';
922 struct _str_ctx_a ctx = {len, str};
923 int ret;
925 ret = pf_printf_a(puts_clbk_str_a, &ctx, format, locale, 0,
926 arg_clbk_valist, NULL, &valist);
927 puts_clbk_str_a(&ctx, 1, &nullbyte);
928 return ret;
931 /*********************************************************************
932 * _vsprintf_l (MSVCRT.@)
934 int CDECL MSVCRT_vsprintf_l( char *str, const char *format,
935 MSVCRT__locale_t locale, __ms_va_list valist )
937 return MSVCRT_vsnprintf_l(str, INT_MAX, format, locale, valist);
940 /*********************************************************************
941 * _sprintf_l (MSVCRT.@)
943 int WINAPIV MSVCRT_sprintf_l(char *str, const char *format,
944 MSVCRT__locale_t locale, ...)
946 int retval;
947 __ms_va_list valist;
948 __ms_va_start(valist, locale);
949 retval = MSVCRT_vsnprintf_l(str, INT_MAX, format, locale, valist);
950 __ms_va_end(valist);
951 return retval;
954 static int CDECL MSVCRT_vsnprintf_s_l_opt( char *str, MSVCRT_size_t sizeOfBuffer,
955 MSVCRT_size_t count, const char *format, DWORD options,
956 MSVCRT__locale_t locale, __ms_va_list valist )
958 static const char nullbyte = '\0';
959 struct _str_ctx_a ctx;
960 int len, ret;
962 if(sizeOfBuffer<count+1 || count==-1)
963 len = sizeOfBuffer;
964 else
965 len = count+1;
967 ctx.len = len;
968 ctx.buf = str;
969 ret = pf_printf_a(puts_clbk_str_a, &ctx, format, locale, MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
970 arg_clbk_valist, NULL, &valist);
971 puts_clbk_str_a(&ctx, 1, &nullbyte);
973 if(ret<0 || ret==len) {
974 if(count!=MSVCRT__TRUNCATE && count>sizeOfBuffer) {
975 MSVCRT_INVALID_PMT("str[sizeOfBuffer] is too small", MSVCRT_ERANGE);
976 memset(str, 0, sizeOfBuffer);
977 } else
978 str[len-1] = '\0';
980 return -1;
983 return ret;
986 static int MSVCRT_vsnwprintf_s_l_opt( MSVCRT_wchar_t *str, MSVCRT_size_t sizeOfBuffer,
987 MSVCRT_size_t count, const MSVCRT_wchar_t *format, DWORD options,
988 MSVCRT__locale_t locale, __ms_va_list valist)
990 static const MSVCRT_wchar_t nullbyte = '\0';
991 struct _str_ctx_w ctx;
992 int len, ret;
994 len = sizeOfBuffer;
995 if(count!=-1 && len>count+1)
996 len = count+1;
998 ctx.len = len;
999 ctx.buf = str;
1000 ret = pf_printf_w(puts_clbk_str_w, &ctx, format, locale, MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
1001 arg_clbk_valist, NULL, &valist);
1002 puts_clbk_str_w(&ctx, 1, &nullbyte);
1004 if(ret<0 || ret==len) {
1005 if(count!=MSVCRT__TRUNCATE && count>sizeOfBuffer) {
1006 MSVCRT_INVALID_PMT("str[sizeOfBuffer] is too small", MSVCRT_ERANGE);
1007 memset(str, 0, sizeOfBuffer*sizeof(MSVCRT_wchar_t));
1008 } else
1009 str[len-1] = '\0';
1011 return -1;
1014 return ret;
1017 /*********************************************************************
1018 * _vsnprintf_s_l (MSVCRT.@)
1020 int CDECL MSVCRT_vsnprintf_s_l( char *str, MSVCRT_size_t sizeOfBuffer,
1021 MSVCRT_size_t count, const char *format,
1022 MSVCRT__locale_t locale, __ms_va_list valist )
1024 return MSVCRT_vsnprintf_s_l_opt(str, sizeOfBuffer, count, format, 0, locale, valist);
1027 /*********************************************************************
1028 * _vsprintf_s_l (MSVCRT.@)
1030 int CDECL MSVCRT_vsprintf_s_l( char *str, MSVCRT_size_t count, const char *format,
1031 MSVCRT__locale_t locale, __ms_va_list valist )
1033 return MSVCRT_vsnprintf_s_l(str, INT_MAX, count, format, locale, valist);
1036 /*********************************************************************
1037 * _sprintf_s_l (MSVCRT.@)
1039 int WINAPIV MSVCRT_sprintf_s_l( char *str, MSVCRT_size_t count, const char *format,
1040 MSVCRT__locale_t locale, ...)
1042 int retval;
1043 __ms_va_list valist;
1044 __ms_va_start(valist, locale);
1045 retval = MSVCRT_vsnprintf_s_l(str, INT_MAX, count, format, locale, valist);
1046 __ms_va_end(valist);
1047 return retval;
1050 /*********************************************************************
1051 * _vsnprintf_s (MSVCRT.@)
1053 int CDECL MSVCRT_vsnprintf_s( char *str, MSVCRT_size_t sizeOfBuffer,
1054 MSVCRT_size_t count, const char *format, __ms_va_list valist )
1056 return MSVCRT_vsnprintf_s_l(str,sizeOfBuffer, count, format, NULL, valist);
1059 /*********************************************************************
1060 * _vsnprintf_c_l (MSVCRT.@)
1062 int CDECL MSVCRT_vsnprintf_c_l(char *str, MSVCRT_size_t len, const char *format,
1063 MSVCRT__locale_t locale, __ms_va_list valist)
1065 return MSVCRT_vsnprintf_s_l_opt(str, len, len, format, 0, locale, valist);
1068 /*********************************************************************
1069 * _vsnprintf_c (MSVCRT.@)
1071 int CDECL MSVCRT_vsnprintf_c(char *str, MSVCRT_size_t len,
1072 const char *format, __ms_va_list valist)
1074 return MSVCRT_vsnprintf_c_l(str, len, format, NULL, valist);
1077 #if _MSVCR_VER>=140
1079 /*********************************************************************
1080 * __stdio_common_vsnprintf_s (UCRTBASE.@)
1082 int CDECL MSVCRT__stdio_common_vsnprintf_s( unsigned __int64 options,
1083 char *str, MSVCRT_size_t sizeOfBuffer, MSVCRT_size_t count,
1084 const char *format, MSVCRT__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 MSVCRT_vsnprintf_s_l_opt(str, sizeOfBuffer, count, format, options & UCRTBASE_PRINTF_MASK, locale, valist);
1091 /*********************************************************************
1092 * __stdio_common_vsnwprintf_s (UCRTBASE.@)
1094 int CDECL MSVCRT__stdio_common_vsnwprintf_s( unsigned __int64 options,
1095 MSVCRT_wchar_t *str, MSVCRT_size_t sizeOfBuffer, MSVCRT_size_t count,
1096 const MSVCRT_wchar_t *format, MSVCRT__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 MSVCRT_vsnwprintf_s_l_opt(str, sizeOfBuffer, count, format, options & UCRTBASE_PRINTF_MASK, locale, valist);
1103 /*********************************************************************
1104 * __stdio_common_vswprintf_s (UCRTBASE.@)
1106 int CDECL MSVCRT__stdio_common_vswprintf_s( unsigned __int64 options,
1107 MSVCRT_wchar_t *str, MSVCRT_size_t count, const MSVCRT_wchar_t *format,
1108 MSVCRT__locale_t locale, __ms_va_list valist )
1110 return MSVCRT__stdio_common_vsnwprintf_s(options, str, INT_MAX, count, format, locale, valist);
1113 /*********************************************************************
1114 * __stdio_common_vsprintf_s (UCRTBASE.@)
1116 int CDECL MSVCRT__stdio_common_vsprintf_s( unsigned __int64 options,
1117 char *str, MSVCRT_size_t count, const char *format,
1118 MSVCRT__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 MSVCRT_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 MSVCRT_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 MSVCRT_vsprintf_s( char *str, MSVCRT_size_t num, const char *format, __ms_va_list valist)
1140 return vsnprintf(str, num, format, valist);
1143 /*********************************************************************
1144 * _vscprintf (MSVCRT.@)
1146 int CDECL MSVCRT__vscprintf( const char *format, __ms_va_list valist )
1148 return MSVCRT_vsnprintf_l( NULL, INT_MAX, format, NULL, valist );
1151 /*********************************************************************
1152 * _vscprintf_l (MSVCRT.@)
1154 int CDECL MSVCRT__vscprintf_l(const char *format,
1155 MSVCRT__locale_t locale, __ms_va_list valist)
1157 return MSVCRT_vsnprintf_l(NULL, INT_MAX, format, locale, valist);
1160 /*********************************************************************
1161 * _vscprintf_p_l (MSVCRT.@)
1163 int CDECL MSVCRT__vscprintf_p_l(const char *format,
1164 MSVCRT__locale_t locale, __ms_va_list args)
1166 printf_arg args_ctx[MSVCRT__ARGMAX+1];
1167 struct _str_ctx_a puts_ctx = {INT_MAX, NULL};
1168 int ret;
1170 memset(args_ctx, 0, sizeof(args_ctx));
1172 ret = create_positional_ctx_a(args_ctx, format, args);
1173 if(ret < 0) {
1174 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
1175 *MSVCRT__errno() = MSVCRT_EINVAL;
1176 return ret;
1177 } else if(ret == 0) {
1178 ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale,
1179 MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER,
1180 arg_clbk_valist, NULL, &args);
1181 } else {
1182 ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale,
1183 MSVCRT_PRINTF_POSITIONAL_PARAMS | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER,
1184 arg_clbk_positional, args_ctx, NULL);
1187 return ret;
1190 /*********************************************************************
1191 * _vscprintf_p (MSVCR80.@)
1193 int CDECL MSVCRT__vscprintf_p(const char *format, __ms_va_list argptr)
1195 return MSVCRT__vscprintf_p_l(format, NULL, argptr);
1198 /*********************************************************************
1199 * _snprintf (MSVCRT.@)
1201 int WINAPIV MSVCRT__snprintf(char *str, MSVCRT_size_t len, const char *format, ...)
1203 int retval;
1204 __ms_va_list valist;
1205 __ms_va_start(valist, format);
1206 retval = vsnprintf(str, len, format, valist);
1207 __ms_va_end(valist);
1208 return retval;
1211 /*********************************************************************
1212 * _snprintf_l (MSVCRT.@)
1214 int WINAPIV MSVCRT__snprintf_l(char *str, MSVCRT_size_t count, const char *format,
1215 MSVCRT__locale_t locale, ...)
1217 int retval;
1218 __ms_va_list valist;
1219 __ms_va_start(valist, locale);
1220 retval = MSVCRT_vsnprintf_l(str, count, format, locale, valist);
1221 __ms_va_end(valist);
1222 return retval;
1225 /*********************************************************************
1226 * _snprintf_c_l (MSVCRT.@)
1228 int WINAPIV MSVCRT_snprintf_c_l(char *str, MSVCRT_size_t count, const char *format,
1229 MSVCRT__locale_t locale, ...)
1231 int retval;
1232 __ms_va_list valist;
1233 __ms_va_start(valist, locale);
1234 retval = MSVCRT_vsnprintf_c_l(str, count, format, locale, valist);
1235 __ms_va_end(valist);
1236 return retval;
1239 /*********************************************************************
1240 * _snprintf_c (MSVCRT.@)
1242 int WINAPIV MSVCRT_snprintf_c(char *str, MSVCRT_size_t count, const char *format, ...)
1244 int retval;
1245 __ms_va_list valist;
1246 __ms_va_start(valist, format);
1247 retval = MSVCRT_vsnprintf_c(str, count, format, valist);
1248 __ms_va_end(valist);
1249 return retval;
1252 /*********************************************************************
1253 * _snprintf_s_l (MSVCRT.@)
1255 int WINAPIV MSVCRT_snprintf_s_l(char *str, MSVCRT_size_t len, MSVCRT_size_t count,
1256 const char *format, MSVCRT__locale_t locale, ...)
1258 int retval;
1259 __ms_va_list valist;
1260 __ms_va_start(valist, locale);
1261 retval = MSVCRT_vsnprintf_s_l(str, len, count, format, locale, valist);
1262 __ms_va_end(valist);
1263 return retval;
1266 /*********************************************************************
1267 * _snprintf_s (MSVCRT.@)
1269 int WINAPIV MSVCRT__snprintf_s(char *str, MSVCRT_size_t len, MSVCRT_size_t count,
1270 const char *format, ...)
1272 int retval;
1273 __ms_va_list valist;
1274 __ms_va_start(valist, format);
1275 retval = MSVCRT_vsnprintf_s_l(str, len, count, format, NULL, valist);
1276 __ms_va_end(valist);
1277 return retval;
1280 /*********************************************************************
1281 * _scprintf (MSVCRT.@)
1283 int WINAPIV MSVCRT__scprintf(const char *format, ...)
1285 int retval;
1286 __ms_va_list valist;
1287 __ms_va_start(valist, format);
1288 retval = MSVCRT__vscprintf(format, valist);
1289 __ms_va_end(valist);
1290 return retval;
1293 /*********************************************************************
1294 * _vsnwprintf (MSVCRT.@)
1296 int CDECL MSVCRT_vsnwprintf(MSVCRT_wchar_t *str, MSVCRT_size_t len,
1297 const MSVCRT_wchar_t *format, __ms_va_list valist)
1299 static const MSVCRT_wchar_t nullbyte = '\0';
1300 struct _str_ctx_w ctx = {len, str};
1301 int ret;
1303 ret = pf_printf_w(puts_clbk_str_w, &ctx, format, NULL, 0,
1304 arg_clbk_valist, NULL, &valist);
1305 puts_clbk_str_w(&ctx, 1, &nullbyte);
1306 return ret;
1309 /*********************************************************************
1310 * _vsnwprintf_l (MSVCRT.@)
1312 int CDECL MSVCRT_vsnwprintf_l(MSVCRT_wchar_t *str, MSVCRT_size_t len,
1313 const MSVCRT_wchar_t *format, MSVCRT__locale_t locale,
1314 __ms_va_list valist)
1316 static const MSVCRT_wchar_t nullbyte = '\0';
1317 struct _str_ctx_w ctx = {len, str};
1318 int ret;
1320 ret = pf_printf_w(puts_clbk_str_w, &ctx, format, locale, 0,
1321 arg_clbk_valist, NULL, &valist);
1322 puts_clbk_str_w(&ctx, 1, &nullbyte);
1323 return ret;
1326 /*********************************************************************
1327 * _vswprintf_c_l (MSVCRT.@)
1329 int CDECL MSVCRT_vswprintf_c_l(MSVCRT_wchar_t *str, MSVCRT_size_t len,
1330 const MSVCRT_wchar_t *format, MSVCRT__locale_t locale,
1331 __ms_va_list valist)
1333 return MSVCRT_vsnwprintf_s_l_opt(str, len, len, format, 0, locale, valist);
1336 /*********************************************************************
1337 * _vswprintf_c (MSVCRT.@)
1339 int CDECL MSVCRT_vswprintf_c(MSVCRT_wchar_t *str, MSVCRT_size_t len,
1340 const MSVCRT_wchar_t *format, __ms_va_list valist)
1342 return MSVCRT_vswprintf_c_l(str, len, format, NULL, valist);
1345 static int MSVCRT_vswprintf_p_l_opt(MSVCRT_wchar_t *buffer, MSVCRT_size_t length,
1346 const MSVCRT_wchar_t *format, DWORD options, MSVCRT__locale_t locale, __ms_va_list args)
1348 static const MSVCRT_wchar_t nullbyte = '\0';
1349 printf_arg args_ctx[MSVCRT__ARGMAX+1];
1350 struct _str_ctx_w puts_ctx = {length, buffer};
1351 int ret;
1353 memset(args_ctx, 0, sizeof(args_ctx));
1355 ret = create_positional_ctx_w(args_ctx, format, args);
1356 if(ret < 0) {
1357 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
1358 *MSVCRT__errno() = MSVCRT_EINVAL;
1359 return ret;
1360 } else if(ret == 0)
1361 ret = pf_printf_w(puts_clbk_str_w, &puts_ctx, format, locale, MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
1362 arg_clbk_valist, NULL, &args);
1363 else
1364 ret = pf_printf_w(puts_clbk_str_w, &puts_ctx, format, locale,
1365 MSVCRT_PRINTF_POSITIONAL_PARAMS | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
1366 arg_clbk_positional, args_ctx, NULL);
1368 puts_clbk_str_w(&puts_ctx, 1, &nullbyte);
1369 return ret;
1372 /*********************************************************************
1373 * _vswprintf_p_l (MSVCRT.@)
1375 int CDECL MSVCRT_vswprintf_p_l(MSVCRT_wchar_t *buffer, MSVCRT_size_t length,
1376 const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, __ms_va_list args)
1378 return MSVCRT_vswprintf_p_l_opt(buffer, length, format, 0, locale, args);
1381 #if _MSVCR_VER>=80
1382 /*********************************************************************
1383 * _vswprintf_p (MSVCR80.@)
1385 int CDECL MSVCRT__vswprintf_p(MSVCRT_wchar_t *buffer, MSVCRT_size_t length,
1386 const MSVCRT_wchar_t *format, __ms_va_list args)
1388 return MSVCRT_vswprintf_p_l_opt(buffer, length, format, 0, NULL, args);
1390 #endif
1392 #if _MSVCR_VER>=140
1393 /*********************************************************************
1394 * __stdio_common_vswprintf_p (UCRTBASE.@)
1396 int CDECL MSVCRT__stdio_common_vswprintf_p( unsigned __int64 options,
1397 MSVCRT_wchar_t *str, MSVCRT_size_t count, const MSVCRT_wchar_t *format,
1398 MSVCRT__locale_t locale, __ms_va_list valist )
1400 if (options & ~UCRTBASE_PRINTF_MASK)
1401 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
1402 return MSVCRT_vswprintf_p_l_opt(str, count, format, options & UCRTBASE_PRINTF_MASK, locale, valist);
1404 #endif
1406 /*********************************************************************
1407 * _vsnwprintf_s_l (MSVCRT.@)
1409 int CDECL MSVCRT_vsnwprintf_s_l( MSVCRT_wchar_t *str, MSVCRT_size_t sizeOfBuffer,
1410 MSVCRT_size_t count, const MSVCRT_wchar_t *format,
1411 MSVCRT__locale_t locale, __ms_va_list valist)
1413 return MSVCRT_vsnwprintf_s_l_opt(str, sizeOfBuffer, count, format, 0, locale, valist);
1416 /*********************************************************************
1417 * _vsnwprintf_s (MSVCRT.@)
1419 int CDECL MSVCRT_vsnwprintf_s(MSVCRT_wchar_t *str, MSVCRT_size_t sizeOfBuffer,
1420 MSVCRT_size_t count, const MSVCRT_wchar_t *format, __ms_va_list valist)
1422 return MSVCRT_vsnwprintf_s_l(str, sizeOfBuffer, count,
1423 format, NULL, valist);
1426 /*********************************************************************
1427 * _snwprintf (MSVCRT.@)
1429 int WINAPIV MSVCRT__snwprintf( MSVCRT_wchar_t *str, MSVCRT_size_t len, const MSVCRT_wchar_t *format, ...)
1431 int retval;
1432 __ms_va_list valist;
1433 __ms_va_start(valist, format);
1434 retval = MSVCRT_vsnwprintf(str, len, format, valist);
1435 __ms_va_end(valist);
1436 return retval;
1439 /*********************************************************************
1440 * _snwprintf_l (MSVCRT.@)
1442 int WINAPIV MSVCRT__snwprintf_l( MSVCRT_wchar_t *str, MSVCRT_size_t len, const MSVCRT_wchar_t *format,
1443 MSVCRT__locale_t locale, ...)
1445 int retval;
1446 __ms_va_list valist;
1447 __ms_va_start(valist, locale);
1448 retval = MSVCRT_vsnwprintf_l(str, len, format, locale, valist);
1449 __ms_va_end(valist);
1450 return retval;
1453 /*********************************************************************
1454 * _snwprintf_s (MSVCRT.@)
1456 int WINAPIV MSVCRT__snwprintf_s( MSVCRT_wchar_t *str, MSVCRT_size_t len, MSVCRT_size_t count,
1457 const MSVCRT_wchar_t *format, ...)
1459 int retval;
1460 __ms_va_list valist;
1461 __ms_va_start(valist, format);
1462 retval = MSVCRT_vsnwprintf_s_l(str, len, count, format, NULL, valist);
1463 __ms_va_end(valist);
1464 return retval;
1467 /*********************************************************************
1468 * _snwprintf_s_l (MSVCRT.@)
1470 int WINAPIV MSVCRT__snwprintf_s_l( MSVCRT_wchar_t *str, MSVCRT_size_t len, MSVCRT_size_t count,
1471 const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, ... )
1473 int retval;
1474 __ms_va_list valist;
1475 __ms_va_start(valist, locale);
1476 retval = MSVCRT_vsnwprintf_s_l(str, len, count, format, locale, valist);
1477 __ms_va_end(valist);
1478 return retval;
1481 #if _MSVCR_VER>=140
1483 static int puts_clbk_str_c99_w(void *ctx, int len, const MSVCRT_wchar_t *str)
1485 struct _str_ctx_w *out = ctx;
1487 if(!out->buf)
1488 return len;
1490 if(out->len < len) {
1491 memcpy(out->buf, str, out->len*sizeof(MSVCRT_wchar_t));
1492 out->buf += out->len;
1493 out->len = 0;
1494 return len;
1497 memcpy(out->buf, str, len*sizeof(MSVCRT_wchar_t));
1498 out->buf += len;
1499 out->len -= len;
1500 return len;
1503 /*********************************************************************
1504 * __stdio_common_vswprintf (UCRTBASE.@)
1506 int CDECL MSVCRT__stdio_common_vswprintf( unsigned __int64 options,
1507 MSVCRT_wchar_t *str, MSVCRT_size_t len, const MSVCRT_wchar_t *format,
1508 MSVCRT__locale_t locale, __ms_va_list valist )
1510 static const MSVCRT_wchar_t nullbyte = '\0';
1511 struct _str_ctx_w ctx = {len, str};
1512 int ret;
1514 if (options & ~UCRTBASE_PRINTF_MASK)
1515 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
1516 ret = pf_printf_w(puts_clbk_str_c99_w,
1517 &ctx, format, locale, options & UCRTBASE_PRINTF_MASK, arg_clbk_valist, NULL, &valist);
1518 puts_clbk_str_w(&ctx, 1, &nullbyte);
1520 if(!str)
1521 return ret;
1522 if(options & UCRTBASE_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION)
1523 return ret>len ? -1 : ret;
1524 if(ret>=len) {
1525 if(len) str[len-1] = 0;
1526 if(options & UCRTBASE_PRINTF_STANDARD_SNPRINTF_BEHAVIOUR)
1527 return ret;
1528 return len > 0 ? -2 : -1;
1530 return ret;
1533 #endif /* _MSVCR_VER>=140 */
1535 /*********************************************************************
1536 * sprintf (MSVCRT.@)
1538 int WINAPIV MSVCRT_sprintf( char *str, const char *format, ... )
1540 __ms_va_list ap;
1541 int r;
1543 __ms_va_start( ap, format );
1544 r = vsnprintf( str, INT_MAX, format, ap );
1545 __ms_va_end( ap );
1546 return r;
1549 /*********************************************************************
1550 * sprintf_s (MSVCRT.@)
1552 int WINAPIV MSVCRT_sprintf_s( char *str, MSVCRT_size_t num, const char *format, ... )
1554 __ms_va_list ap;
1555 int r;
1557 __ms_va_start( ap, format );
1558 r = vsnprintf( str, num, format, ap );
1559 __ms_va_end( ap );
1560 return r;
1563 /*********************************************************************
1564 * _scwprintf (MSVCRT.@)
1566 int WINAPIV MSVCRT__scwprintf( const MSVCRT_wchar_t *format, ... )
1568 __ms_va_list ap;
1569 int r;
1571 __ms_va_start( ap, format );
1572 r = MSVCRT_vsnwprintf( NULL, INT_MAX, format, ap );
1573 __ms_va_end( ap );
1574 return r;
1577 /*********************************************************************
1578 * swprintf (MSVCRT.@)
1580 int WINAPIV MSVCRT_swprintf( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *format, ... )
1582 __ms_va_list ap;
1583 int r;
1585 __ms_va_start( ap, format );
1586 r = MSVCRT_vsnwprintf( str, INT_MAX, format, ap );
1587 __ms_va_end( ap );
1588 return r;
1591 /*********************************************************************
1592 * swprintf_s (MSVCRT.@)
1594 int WINAPIV MSVCRT_swprintf_s(MSVCRT_wchar_t *str, MSVCRT_size_t numberOfElements,
1595 const MSVCRT_wchar_t *format, ... )
1597 __ms_va_list ap;
1598 int r;
1600 __ms_va_start(ap, format);
1601 r = MSVCRT_vsnwprintf_s(str, numberOfElements, INT_MAX, format, ap);
1602 __ms_va_end(ap);
1604 return r;
1607 /*********************************************************************
1608 * _swprintf_s_l (MSVCRT.@)
1610 int WINAPIV MSVCRT__swprintf_s_l(MSVCRT_wchar_t *str, MSVCRT_size_t numberOfElements,
1611 const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, ... )
1613 __ms_va_list ap;
1614 int r;
1616 __ms_va_start(ap, locale);
1617 r = MSVCRT_vsnwprintf_s_l(str, numberOfElements, INT_MAX, format, locale, ap);
1618 __ms_va_end(ap);
1620 return r;
1623 /*********************************************************************
1624 * _swprintf_c_l (MSVCRT.@)
1626 int WINAPIV MSVCRT_swprintf_c_l(MSVCRT_wchar_t *str, MSVCRT_size_t len,
1627 const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, ... )
1629 __ms_va_list ap;
1630 int r;
1632 __ms_va_start(ap, locale);
1633 r = MSVCRT_vswprintf_c_l(str, len, format, locale, ap);
1634 __ms_va_end(ap);
1636 return r;
1639 /*********************************************************************
1640 * _swprintf_c (MSVCRT.@)
1642 int WINAPIV MSVCRT_swprintf_c(MSVCRT_wchar_t *str, MSVCRT_size_t len,
1643 const MSVCRT_wchar_t *format, ... )
1645 __ms_va_list ap;
1646 int r;
1648 __ms_va_start(ap, format);
1649 r = MSVCRT_vswprintf_c(str, len, format, ap);
1650 __ms_va_end(ap);
1652 return r;
1655 /*********************************************************************
1656 * _vswprintf (MSVCRT.@)
1658 int CDECL MSVCRT_vswprintf( MSVCRT_wchar_t* str, const MSVCRT_wchar_t* format, __ms_va_list args )
1660 return MSVCRT_vsnwprintf( str, INT_MAX, format, args );
1663 /*********************************************************************
1664 * _vswprintf (MSVCRT.@)
1666 int CDECL MSVCRT_vswprintf_l( MSVCRT_wchar_t* str, const MSVCRT_wchar_t* format,
1667 MSVCRT__locale_t locale, __ms_va_list args )
1669 return MSVCRT_vsnwprintf_l( str, INT_MAX, format, locale, args );
1672 /*********************************************************************
1673 * _vscwprintf (MSVCRT.@)
1675 int CDECL MSVCRT__vscwprintf( const MSVCRT_wchar_t *format, __ms_va_list args )
1677 return MSVCRT_vsnwprintf( NULL, INT_MAX, format, args );
1680 /*********************************************************************
1681 * _vscwprintf_l (MSVCRT.@)
1683 int CDECL MSVCRT__vscwprintf_l( const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, __ms_va_list args )
1685 return MSVCRT_vsnwprintf_l( NULL, INT_MAX, format, locale, args );
1688 /*********************************************************************
1689 * _vscwprintf_p_l (MSVCRT.@)
1691 int CDECL MSVCRT__vscwprintf_p_l( const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, __ms_va_list args )
1693 return MSVCRT_vswprintf_p_l_opt( NULL, INT_MAX, format, 0, locale, args );
1696 #if _MSVCR_VER>=80
1697 /*********************************************************************
1698 * _vscwprintf_p (MSVCR80.@)
1700 int CDECL MSVCRT__vscwprintf_p(const MSVCRT_wchar_t *format, __ms_va_list args)
1702 return MSVCRT_vswprintf_p_l_opt(NULL, INT_MAX, format, 0, NULL, args);
1704 #endif
1706 /*********************************************************************
1707 * vswprintf_s (MSVCRT.@)
1709 int CDECL MSVCRT_vswprintf_s(MSVCRT_wchar_t* str, MSVCRT_size_t numberOfElements,
1710 const MSVCRT_wchar_t* format, __ms_va_list args)
1712 return MSVCRT_vsnwprintf_s(str, numberOfElements, INT_MAX, format, args );
1715 /*********************************************************************
1716 * _vswprintf_s_l (MSVCRT.@)
1718 int CDECL MSVCRT_vswprintf_s_l(MSVCRT_wchar_t* str, MSVCRT_size_t numberOfElements,
1719 const MSVCRT_wchar_t* format, MSVCRT__locale_t locale, __ms_va_list args)
1721 return MSVCRT_vsnwprintf_s_l(str, numberOfElements, INT_MAX,
1722 format, locale, args );
1725 static int MSVCRT_vsprintf_p_l_opt(char *buffer, MSVCRT_size_t length, const char *format,
1726 DWORD options, MSVCRT__locale_t locale, __ms_va_list args)
1728 static const char nullbyte = '\0';
1729 printf_arg args_ctx[MSVCRT__ARGMAX+1];
1730 struct _str_ctx_a puts_ctx = {length, buffer};
1731 int ret;
1733 memset(args_ctx, 0, sizeof(args_ctx));
1735 ret = create_positional_ctx_a(args_ctx, format, args);
1736 if(ret < 0) {
1737 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
1738 *MSVCRT__errno() = MSVCRT_EINVAL;
1739 return ret;
1740 } else if(ret == 0)
1741 ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale,
1742 MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options, arg_clbk_valist, NULL, &args);
1743 else
1744 ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale,
1745 MSVCRT_PRINTF_POSITIONAL_PARAMS | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
1746 arg_clbk_positional, args_ctx, NULL);
1748 puts_clbk_str_a(&puts_ctx, 1, &nullbyte);
1749 return ret;
1752 /*********************************************************************
1753 * _vsprintf_p_l (MSVCRT.@)
1755 int CDECL MSVCRT_vsprintf_p_l(char *buffer, MSVCRT_size_t length, const char *format,
1756 MSVCRT__locale_t locale, __ms_va_list args)
1758 return MSVCRT_vsprintf_p_l_opt(buffer, length, format, 0, locale, args);
1761 /*********************************************************************
1762 * _vsprintf_p (MSVCRT.@)
1764 int CDECL MSVCRT_vsprintf_p(char *buffer, MSVCRT_size_t length,
1765 const char *format, __ms_va_list args)
1767 return MSVCRT_vsprintf_p_l(buffer, length, format, NULL, args);
1770 #if _MSVCR_VER>=140
1771 /*********************************************************************
1772 * __stdio_common_vsprintf_p (UCRTBASE.@)
1774 int CDECL MSVCRT__stdio_common_vsprintf_p(unsigned __int64 options, char *buffer, MSVCRT_size_t length,
1775 const char *format, MSVCRT__locale_t locale, __ms_va_list args)
1777 if (options & ~UCRTBASE_PRINTF_MASK)
1778 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
1779 return MSVCRT_vsprintf_p_l_opt(buffer, length, format, options & UCRTBASE_PRINTF_MASK, locale, args);
1781 #endif
1783 /*********************************************************************
1784 * _sprintf_p_l (MSVCRT.@)
1786 int WINAPIV MSVCRT_sprintf_p_l(char *buffer, MSVCRT_size_t length,
1787 const char *format, MSVCRT__locale_t locale, ...)
1789 __ms_va_list valist;
1790 int r;
1792 __ms_va_start(valist, locale);
1793 r = MSVCRT_vsprintf_p_l(buffer, length, format, locale, valist);
1794 __ms_va_end(valist);
1796 return r;
1799 /*********************************************************************
1800 * __swprintf_l (MSVCRT.@)
1802 int WINAPIV MSVCRT___swprintf_l( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *format,
1803 MSVCRT__locale_t locale, ...)
1805 int retval;
1806 __ms_va_list valist;
1807 __ms_va_start(valist, locale);
1808 retval = MSVCRT_vswprintf_l(str, format, locale, valist);
1809 __ms_va_end(valist);
1810 return retval;
1813 #if _MSVCR_VER>=80
1814 /*********************************************************************
1815 * _sprintf_p (MSVCR80.@)
1817 int WINAPIV MSVCRT__sprintf_p(char *buffer, MSVCRT_size_t length, const char *format, ...)
1819 __ms_va_list valist;
1820 int r;
1822 __ms_va_start(valist, format);
1823 r = MSVCRT_vsprintf_p_l(buffer, length, format, NULL, valist);
1824 __ms_va_end(valist);
1826 return r;
1828 #endif
1830 /*********************************************************************
1831 * _swprintf_p_l (MSVCRT.@)
1833 int WINAPIV MSVCRT_swprintf_p_l(MSVCRT_wchar_t *buffer, MSVCRT_size_t length,
1834 const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, ...)
1836 __ms_va_list valist;
1837 int r;
1839 __ms_va_start(valist, locale);
1840 r = MSVCRT_vswprintf_p_l_opt(buffer, length, format, 0, locale, valist);
1841 __ms_va_end(valist);
1843 return r;
1846 /*********************************************************************
1847 * wcscmp (MSVCRT.@)
1849 int CDECL MSVCRT_wcscmp(const MSVCRT_wchar_t *str1, const MSVCRT_wchar_t *str2)
1851 while (*str1 && (*str1 == *str2))
1853 str1++;
1854 str2++;
1857 if (*str1 < *str2)
1858 return -1;
1859 if (*str1 > *str2)
1860 return 1;
1861 return 0;
1864 /*********************************************************************
1865 * _wcscoll_l (MSVCRT.@)
1867 int CDECL MSVCRT__wcscoll_l(const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2, MSVCRT__locale_t locale)
1869 MSVCRT_pthreadlocinfo locinfo;
1871 if(!locale)
1872 locinfo = get_locinfo();
1873 else
1874 locinfo = locale->locinfo;
1876 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE])
1877 return MSVCRT_wcscmp(str1, str2);
1878 return CompareStringW(locinfo->lc_handle[MSVCRT_LC_COLLATE], 0, str1, -1, str2, -1)-CSTR_EQUAL;
1881 /*********************************************************************
1882 * wcscoll (MSVCRT.@)
1884 int CDECL MSVCRT_wcscoll( const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2 )
1886 return MSVCRT__wcscoll_l(str1, str2, NULL);
1889 /*********************************************************************
1890 * wcspbrk (MSVCRT.@)
1892 MSVCRT_wchar_t* CDECL MSVCRT_wcspbrk( const MSVCRT_wchar_t* str, const MSVCRT_wchar_t* accept )
1894 const MSVCRT_wchar_t* p;
1896 while (*str)
1898 for (p = accept; *p; p++) if (*p == *str) return (MSVCRT_wchar_t*)str;
1899 str++;
1901 return NULL;
1904 /*********************************************************************
1905 * wcstok_s (MSVCRT.@)
1907 MSVCRT_wchar_t * CDECL MSVCRT_wcstok_s( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *delim,
1908 MSVCRT_wchar_t **next_token )
1910 MSVCRT_wchar_t *ret;
1912 if (!MSVCRT_CHECK_PMT(delim != NULL)) return NULL;
1913 if (!MSVCRT_CHECK_PMT(next_token != NULL)) return NULL;
1914 if (!MSVCRT_CHECK_PMT(str != NULL || *next_token != NULL)) return NULL;
1916 if (!str) str = *next_token;
1918 while (*str && MSVCRT_wcschr( delim, *str )) str++;
1919 if (!*str) return NULL;
1920 ret = str++;
1921 while (*str && !MSVCRT_wcschr( delim, *str )) str++;
1922 if (*str) *str++ = 0;
1923 *next_token = str;
1924 return ret;
1927 /*********************************************************************
1928 * wcstok (MSVCRT.@)
1930 #if _MSVCR_VER>=140
1931 MSVCRT_wchar_t * CDECL MSVCRT_wcstok( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *delim, MSVCRT_wchar_t **ctx )
1933 if (!ctx)
1934 ctx = &msvcrt_get_thread_data()->wcstok_next;
1935 return MSVCRT_wcstok_s(str, delim, ctx);
1937 #else
1938 MSVCRT_wchar_t * CDECL MSVCRT_wcstok( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *delim )
1940 return MSVCRT_wcstok_s(str, delim, &msvcrt_get_thread_data()->wcstok_next);
1942 #endif
1944 /*********************************************************************
1945 * _wctomb_s_l (MSVCRT.@)
1947 int CDECL MSVCRT__wctomb_s_l(int *len, char *mbchar, MSVCRT_size_t size,
1948 MSVCRT_wchar_t wch, MSVCRT__locale_t locale)
1950 MSVCRT_pthreadlocinfo locinfo;
1951 BOOL error = FALSE;
1952 BOOL *perror;
1953 int mblen;
1955 if(!mbchar && size>0) {
1956 if(len)
1957 *len = 0;
1958 return 0;
1961 if(len)
1962 *len = -1;
1964 if(!MSVCRT_CHECK_PMT(size <= INT_MAX))
1965 return MSVCRT_EINVAL;
1967 if(!locale)
1968 locinfo = get_locinfo();
1969 else
1970 locinfo = locale->locinfo;
1972 if(!locinfo->lc_codepage) {
1973 if(wch > 0xff) {
1974 if(mbchar && size>0)
1975 memset(mbchar, 0, size);
1976 *MSVCRT__errno() = MSVCRT_EILSEQ;
1977 return MSVCRT_EILSEQ;
1980 if(!MSVCRT_CHECK_PMT_ERR(size >= 1, MSVCRT_ERANGE))
1981 return MSVCRT_ERANGE;
1983 *mbchar = wch;
1984 if(len)
1985 *len = 1;
1986 return 0;
1989 perror = (locinfo->lc_codepage != CP_UTF8 ? &error : NULL);
1990 mblen = WideCharToMultiByte(locinfo->lc_codepage, 0, &wch, 1, mbchar, size, NULL, perror);
1991 if(!mblen || error) {
1992 if(!mblen && GetLastError()==ERROR_INSUFFICIENT_BUFFER) {
1993 if(mbchar && size>0)
1994 memset(mbchar, 0, size);
1996 MSVCRT_INVALID_PMT("insufficient buffer size", MSVCRT_ERANGE);
1997 return MSVCRT_ERANGE;
2000 *MSVCRT__errno() = MSVCRT_EILSEQ;
2001 return MSVCRT_EILSEQ;
2004 if(len)
2005 *len = mblen;
2006 return 0;
2009 /*********************************************************************
2010 * wctomb_s (MSVCRT.@)
2012 int CDECL MSVCRT_wctomb_s(int *len, char *mbchar, MSVCRT_size_t size, MSVCRT_wchar_t wch)
2014 return MSVCRT__wctomb_s_l(len, mbchar, size, wch, NULL);
2017 /*********************************************************************
2018 * _wctomb_l (MSVCRT.@)
2020 int CDECL MSVCRT__wctomb_l(char *dst, MSVCRT_wchar_t ch, MSVCRT__locale_t locale)
2022 int len;
2024 MSVCRT__wctomb_s_l(&len, dst, dst ? MSVCRT_MB_LEN_MAX : 0, ch, locale);
2025 return len;
2028 /*********************************************************************
2029 * wctomb (MSVCRT.@)
2031 INT CDECL MSVCRT_wctomb( char *dst, MSVCRT_wchar_t ch )
2033 return MSVCRT__wctomb_l(dst, ch, NULL);
2036 /*********************************************************************
2037 * wctob (MSVCRT.@)
2039 INT CDECL MSVCRT_wctob( MSVCRT_wint_t wchar )
2041 char out;
2042 BOOL error = FALSE;
2043 BOOL *perror;
2044 UINT codepage = get_locinfo()->lc_codepage;
2046 perror = (codepage != CP_UTF8 ? &error : NULL);
2048 if(!codepage) {
2049 if (wchar < 0xff)
2050 return (signed char)wchar;
2051 else
2052 return MSVCRT_EOF;
2053 } else if(WideCharToMultiByte( codepage, 0, &wchar, 1, &out, 1, NULL, perror ) && !error)
2054 return (INT)out;
2055 return MSVCRT_EOF;
2058 /*********************************************************************
2059 * wcrtomb_s (MSVCRT.@)
2061 INT CDECL MSVCRT_wcrtomb_s(MSVCRT_size_t *len, char *mbchar,
2062 MSVCRT_size_t size, MSVCRT_wchar_t wch, MSVCRT_mbstate_t *s)
2064 int ilen, ret;
2066 if (s) *s = 0;
2067 ret = MSVCRT_wctomb_s(&ilen, mbchar, size, wch);
2068 if (len) *len = ilen;
2069 return ret;
2072 /*********************************************************************
2073 * wcrtomb (MSVCRT.@)
2075 MSVCRT_size_t CDECL MSVCRT_wcrtomb( char *dst, MSVCRT_wchar_t ch, MSVCRT_mbstate_t *s)
2077 if(s)
2078 *s = 0;
2079 return MSVCRT_wctomb(dst, ch);
2082 /*********************************************************************
2083 * _iswctype_l (MSVCRT.@)
2085 INT CDECL MSVCRT__iswctype_l( MSVCRT_wchar_t wc, wctype_t type, MSVCRT__locale_t locale )
2087 WORD ct;
2089 if (wc == MSVCRT_WEOF) return 0;
2090 if (wc < 256) return MSVCRT__pwctype[wc] & type;
2092 if (!GetStringTypeW(CT_CTYPE1, &wc, 1, &ct))
2094 ERR("GetStringTypeW failed for %x\n", wc);
2095 return 0;
2097 return ct & type;
2100 /*********************************************************************
2101 * iswctype (MSVCRT.@)
2103 INT CDECL MSVCRT_iswctype( MSVCRT_wchar_t wc, wctype_t type )
2105 return MSVCRT__iswctype_l( wc, type, NULL );
2108 /*********************************************************************
2109 * _iswalnum_l (MSVCRT.@)
2111 int CDECL MSVCRT__iswalnum_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
2113 return MSVCRT__iswctype_l( wc, MSVCRT__ALPHA | MSVCRT__DIGIT, locale );
2116 /*********************************************************************
2117 * iswalnum (MSVCRT.@)
2119 INT CDECL MSVCRT_iswalnum( MSVCRT_wchar_t wc )
2121 return MSVCRT__iswalnum_l( wc, NULL );
2124 /*********************************************************************
2125 * iswalpha_l (MSVCRT.@)
2127 INT CDECL MSVCRT__iswalpha_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
2129 return MSVCRT__iswctype_l( wc, MSVCRT__ALPHA, locale );
2132 /*********************************************************************
2133 * iswalpha (MSVCRT.@)
2135 INT CDECL MSVCRT_iswalpha( MSVCRT_wchar_t wc )
2137 return MSVCRT__iswalpha_l( wc, NULL );
2140 /*********************************************************************
2141 * _iswcntrl_l (MSVCRT.@)
2143 int CDECL MSVCRT__iswcntrl_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
2145 return MSVCRT__iswctype_l( wc, MSVCRT__CONTROL, locale );
2148 /*********************************************************************
2149 * iswcntrl (MSVCRT.@)
2151 INT CDECL MSVCRT_iswcntrl( MSVCRT_wchar_t wc )
2153 return MSVCRT__iswcntrl_l( wc, NULL );
2156 /*********************************************************************
2157 * _iswdigit_l (MSVCRT.@)
2159 INT CDECL MSVCRT__iswdigit_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
2161 return MSVCRT__iswctype_l( wc, MSVCRT__DIGIT, locale );
2164 /*********************************************************************
2165 * iswdigit (MSVCRT.@)
2167 INT CDECL MSVCRT_iswdigit( MSVCRT_wchar_t wc )
2169 return MSVCRT__iswdigit_l( wc, NULL );
2172 /*********************************************************************
2173 * _iswgraph_l (MSVCRT.@)
2175 int CDECL MSVCRT__iswgraph_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
2177 return MSVCRT__iswctype_l( wc, MSVCRT__ALPHA | MSVCRT__DIGIT | MSVCRT__PUNCT, locale );
2180 /*********************************************************************
2181 * iswgraph (MSVCRT.@)
2183 INT CDECL MSVCRT_iswgraph( MSVCRT_wchar_t wc )
2185 return MSVCRT__iswgraph_l( wc, NULL );
2188 /*********************************************************************
2189 * _iswlower_l (MSVCRT.@)
2191 int CDECL MSVCRT__iswlower_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
2193 return MSVCRT__iswctype_l( wc, MSVCRT__LOWER, locale );
2196 /*********************************************************************
2197 * iswlower (MSVCRT.@)
2199 INT CDECL MSVCRT_iswlower( MSVCRT_wchar_t wc )
2201 return MSVCRT__iswlower_l( wc, NULL );
2204 /*********************************************************************
2205 * _iswprint_l (MSVCRT.@)
2207 int CDECL MSVCRT__iswprint_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
2209 return MSVCRT__iswctype_l( wc, MSVCRT__ALPHA | MSVCRT__BLANK |
2210 MSVCRT__DIGIT | MSVCRT__PUNCT, locale );
2213 /*********************************************************************
2214 * iswprint (MSVCRT.@)
2216 INT CDECL MSVCRT_iswprint( MSVCRT_wchar_t wc )
2218 return MSVCRT__iswprint_l( wc, NULL );
2221 /*********************************************************************
2222 * _iswpunct_l (MSVCRT.@)
2224 INT CDECL MSVCRT__iswpunct_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
2226 return MSVCRT__iswctype_l( wc, MSVCRT__PUNCT, locale );
2229 /*********************************************************************
2230 * iswpunct (MSVCRT.@)
2232 INT CDECL MSVCRT_iswpunct( MSVCRT_wchar_t wc )
2234 return MSVCRT__iswpunct_l( wc, NULL );
2237 /*********************************************************************
2238 * _iswspace_l (MSVCRT.@)
2240 INT CDECL MSVCRT__iswspace_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
2242 return MSVCRT__iswctype_l( wc, MSVCRT__SPACE, locale );
2245 /*********************************************************************
2246 * iswspace (MSVCRT.@)
2248 INT CDECL MSVCRT_iswspace( MSVCRT_wchar_t wc )
2250 return MSVCRT__iswspace_l( wc, NULL );
2253 /*********************************************************************
2254 * _iswupper_l (MSVCRT.@)
2256 int CDECL MSVCRT__iswupper_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
2258 return MSVCRT__iswctype_l( wc, MSVCRT__UPPER, locale );
2261 /*********************************************************************
2262 * iswupper (MSVCRT.@)
2264 INT CDECL MSVCRT_iswupper( MSVCRT_wchar_t wc )
2266 return MSVCRT__iswupper_l( wc, NULL );
2269 /*********************************************************************
2270 * _iswxdigit_l (MSVCRT.@)
2272 int CDECL MSVCRT__iswxdigit_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
2274 return MSVCRT__iswctype_l( wc, MSVCRT__HEX, locale );
2277 /*********************************************************************
2278 * iswxdigit (MSVCRT.@)
2280 INT CDECL MSVCRT_iswxdigit( MSVCRT_wchar_t wc )
2282 return MSVCRT__iswxdigit_l( wc, NULL );
2285 /*********************************************************************
2286 * _iswblank_l (MSVCRT.@)
2288 INT CDECL MSVCRT__iswblank_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
2290 return wc == '\t' || MSVCRT__iswctype_l( wc, MSVCRT__BLANK, locale );
2293 /*********************************************************************
2294 * iswblank (MSVCRT.@)
2296 INT CDECL MSVCRT_iswblank( MSVCRT_wchar_t wc )
2298 return wc == '\t' || MSVCRT__iswctype_l( wc, MSVCRT__BLANK, NULL );
2301 /*********************************************************************
2302 * wcscpy_s (MSVCRT.@)
2304 INT CDECL MSVCRT_wcscpy_s( MSVCRT_wchar_t* wcDest, MSVCRT_size_t numElement, const MSVCRT_wchar_t *wcSrc)
2306 MSVCRT_size_t size = 0;
2308 if(!MSVCRT_CHECK_PMT(wcDest)) return MSVCRT_EINVAL;
2309 if(!MSVCRT_CHECK_PMT(numElement)) return MSVCRT_EINVAL;
2311 if(!MSVCRT_CHECK_PMT(wcSrc))
2313 wcDest[0] = 0;
2314 return MSVCRT_EINVAL;
2317 size = MSVCRT_wcslen(wcSrc) + 1;
2319 if(!MSVCRT_CHECK_PMT_ERR(size <= numElement, MSVCRT_ERANGE))
2321 wcDest[0] = 0;
2322 return MSVCRT_ERANGE;
2325 memmove( wcDest, wcSrc, size*sizeof(WCHAR) );
2327 return 0;
2330 /***********************************************************************
2331 * wcscpy (MSVCRT.@)
2333 MSVCRT_wchar_t* __cdecl MSVCRT_wcscpy( MSVCRT_wchar_t *dst, const MSVCRT_wchar_t *src )
2335 WCHAR *p = dst;
2336 while ((*p++ = *src++));
2337 return dst;
2340 /******************************************************************
2341 * wcsncpy (MSVCRT.@)
2343 MSVCRT_wchar_t* __cdecl MSVCRT_wcsncpy( MSVCRT_wchar_t* s1,
2344 const MSVCRT_wchar_t *s2, MSVCRT_size_t n )
2346 MSVCRT_size_t i;
2348 for(i=0; i<n; i++)
2349 if(!(s1[i] = s2[i])) break;
2350 for(; i<n; i++)
2351 s1[i] = 0;
2352 return s1;
2355 /******************************************************************
2356 * wcsncpy_s (MSVCRT.@)
2358 INT CDECL MSVCRT_wcsncpy_s( MSVCRT_wchar_t* wcDest, MSVCRT_size_t numElement, const MSVCRT_wchar_t *wcSrc,
2359 MSVCRT_size_t count )
2361 WCHAR *p = wcDest;
2362 BOOL truncate = (count == MSVCRT__TRUNCATE);
2364 if(!wcDest && !numElement && !count)
2365 return 0;
2367 if (!wcDest || !numElement)
2368 return MSVCRT_EINVAL;
2370 if (!wcSrc)
2372 *wcDest = 0;
2373 return count ? MSVCRT_EINVAL : 0;
2376 while (numElement && count && *wcSrc)
2378 *p++ = *wcSrc++;
2379 numElement--;
2380 count--;
2382 if (!numElement && truncate)
2384 *(p-1) = 0;
2385 return MSVCRT_STRUNCATE;
2387 else if (!numElement)
2389 *wcDest = 0;
2390 return MSVCRT_ERANGE;
2393 *p = 0;
2394 return 0;
2397 /******************************************************************
2398 * wcscat_s (MSVCRT.@)
2401 INT CDECL MSVCRT_wcscat_s(MSVCRT_wchar_t* dst, MSVCRT_size_t elem, const MSVCRT_wchar_t* src)
2403 MSVCRT_wchar_t* ptr = dst;
2405 if (!dst || elem == 0) return MSVCRT_EINVAL;
2406 if (!src)
2408 dst[0] = '\0';
2409 return MSVCRT_EINVAL;
2412 /* seek to end of dst string (or elem if no end of string is found */
2413 while (ptr < dst + elem && *ptr != '\0') ptr++;
2414 while (ptr < dst + elem)
2416 if ((*ptr++ = *src++) == '\0') return 0;
2418 /* not enough space */
2419 dst[0] = '\0';
2420 return MSVCRT_ERANGE;
2423 /***********************************************************************
2424 * wcscat (MSVCRT.@)
2426 MSVCRT_wchar_t* __cdecl MSVCRT_wcscat( MSVCRT_wchar_t *dst, const MSVCRT_wchar_t *src )
2428 MSVCRT_wcscpy( dst + MSVCRT_wcslen(dst), src );
2429 return dst;
2432 /*********************************************************************
2433 * wcsncat_s (MSVCRT.@)
2436 INT CDECL MSVCRT_wcsncat_s(MSVCRT_wchar_t *dst, MSVCRT_size_t elem,
2437 const MSVCRT_wchar_t *src, MSVCRT_size_t count)
2439 MSVCRT_size_t srclen;
2440 MSVCRT_wchar_t dststart;
2441 INT ret = 0;
2443 if (!MSVCRT_CHECK_PMT(dst != NULL)) return MSVCRT_EINVAL;
2444 if (!MSVCRT_CHECK_PMT(elem > 0)) return MSVCRT_EINVAL;
2445 if (!MSVCRT_CHECK_PMT(src != NULL || count == 0)) return MSVCRT_EINVAL;
2447 if (count == 0)
2448 return 0;
2450 for (dststart = 0; dststart < elem; dststart++)
2452 if (dst[dststart] == '\0')
2453 break;
2455 if (dststart == elem)
2457 MSVCRT_INVALID_PMT("dst[elem] is not NULL terminated\n", MSVCRT_EINVAL);
2458 return MSVCRT_EINVAL;
2461 if (count == MSVCRT__TRUNCATE)
2463 srclen = MSVCRT_wcslen(src);
2464 if (srclen >= (elem - dststart))
2466 srclen = elem - dststart - 1;
2467 ret = MSVCRT_STRUNCATE;
2470 else
2471 srclen = min(MSVCRT_wcslen(src), count);
2472 if (srclen < (elem - dststart))
2474 memcpy(&dst[dststart], src, srclen*sizeof(MSVCRT_wchar_t));
2475 dst[dststart+srclen] = '\0';
2476 return ret;
2478 MSVCRT_INVALID_PMT("dst[elem] is too small", MSVCRT_ERANGE);
2479 dst[0] = '\0';
2480 return MSVCRT_ERANGE;
2483 /*********************************************************************
2484 * wctoint (INTERNAL)
2486 static int wctoint(WCHAR c, int base)
2488 int v = -1;
2489 if ('0' <= c && c <= '9')
2490 v = c - '0';
2491 else if ('A' <= c && c <= 'Z')
2492 v = c - 'A' + 10;
2493 else if ('a' <= c && c <= 'z')
2494 v = c - 'a' + 10;
2495 else {
2496 /* NOTE: wine_fold_string(MAP_FOLDDIGITS) supports too many things. */
2497 /* Unicode points that contain digits 0-9; keep this sorted! */
2498 static const WCHAR zeros[] = {
2499 0x660, 0x6f0, 0x966, 0x9e6, 0xa66, 0xae6, 0xb66, 0xc66, 0xce6,
2500 0xd66, 0xe50, 0xed0, 0xf20, 0x1040, 0x17e0, 0x1810, 0xff10
2502 int i;
2503 for (i = 0; i < ARRAY_SIZE(zeros) && c >= zeros[i]; ++i) {
2504 if (zeros[i] <= c && c <= zeros[i] + 9) {
2505 v = c - zeros[i];
2506 break;
2510 return v < base ? v : -1;
2513 /*********************************************************************
2514 * _wcstoi64_l (MSVCRT.@)
2516 * FIXME: locale parameter is ignored
2518 __int64 CDECL MSVCRT__wcstoi64_l(const MSVCRT_wchar_t *nptr,
2519 MSVCRT_wchar_t **endptr, int base, MSVCRT__locale_t locale)
2521 BOOL negative = FALSE, empty = TRUE;
2522 __int64 ret = 0;
2524 TRACE("(%s %p %d %p)\n", debugstr_w(nptr), endptr, base, locale);
2526 if (!MSVCRT_CHECK_PMT(nptr != NULL)) return 0;
2527 if (!MSVCRT_CHECK_PMT(base == 0 || base >= 2)) return 0;
2528 if (!MSVCRT_CHECK_PMT(base <= 36)) return 0;
2530 if(endptr)
2531 *endptr = (MSVCRT_wchar_t*)nptr;
2533 while(MSVCRT__iswspace_l(*nptr, locale)) nptr++;
2535 if(*nptr == '-') {
2536 negative = TRUE;
2537 nptr++;
2538 } else if(*nptr == '+')
2539 nptr++;
2541 if((base==0 || base==16) && wctoint(*nptr, 1)==0 && (nptr[1]=='x' || nptr[1]=='X')) {
2542 base = 16;
2543 nptr += 2;
2546 if(base == 0) {
2547 if(wctoint(*nptr, 1)==0)
2548 base = 8;
2549 else
2550 base = 10;
2553 while(*nptr) {
2554 int v = wctoint(*nptr, base);
2555 if(v<0)
2556 break;
2558 if(negative)
2559 v = -v;
2561 nptr++;
2562 empty = FALSE;
2564 if(!negative && (ret>MSVCRT_I64_MAX/base || ret*base>MSVCRT_I64_MAX-v)) {
2565 ret = MSVCRT_I64_MAX;
2566 *MSVCRT__errno() = MSVCRT_ERANGE;
2567 } else if(negative && (ret<MSVCRT_I64_MIN/base || ret*base<MSVCRT_I64_MIN-v)) {
2568 ret = MSVCRT_I64_MIN;
2569 *MSVCRT__errno() = MSVCRT_ERANGE;
2570 } else
2571 ret = ret*base + v;
2574 if(endptr && !empty)
2575 *endptr = (MSVCRT_wchar_t*)nptr;
2577 return ret;
2580 /*********************************************************************
2581 * _wcstoi64 (MSVCRT.@)
2583 __int64 CDECL MSVCRT__wcstoi64(const MSVCRT_wchar_t *nptr,
2584 MSVCRT_wchar_t **endptr, int base)
2586 return MSVCRT__wcstoi64_l(nptr, endptr, base, NULL);
2589 /*********************************************************************
2590 * _wcstol_l (MSVCRT.@)
2592 MSVCRT_long CDECL MSVCRT__wcstol_l(const MSVCRT_wchar_t *s,
2593 MSVCRT_wchar_t **end, int base, MSVCRT__locale_t locale)
2595 __int64 ret = MSVCRT__wcstoi64_l(s, end, base, locale);
2597 if(ret > MSVCRT_LONG_MAX) {
2598 ret = MSVCRT_LONG_MAX;
2599 *MSVCRT__errno() = MSVCRT_ERANGE;
2600 }else if(ret < MSVCRT_LONG_MIN) {
2601 ret = MSVCRT_LONG_MIN;
2602 *MSVCRT__errno() = MSVCRT_ERANGE;
2604 return ret;
2607 /*********************************************************************
2608 * wcstol (MSVCRT.@)
2610 MSVCRT_long CDECL MSVCRT_wcstol(const MSVCRT_wchar_t *s,
2611 MSVCRT_wchar_t **end, int base)
2613 return MSVCRT__wcstol_l(s, end, base, NULL);
2616 /*********************************************************************
2617 * _wtoi_l (MSVCRT.@)
2619 int __cdecl MSVCRT__wtoi_l(const MSVCRT_wchar_t *str, MSVCRT__locale_t locale)
2621 __int64 ret = MSVCRT__wcstoi64_l(str, NULL, 10, locale);
2623 if(ret > INT_MAX) {
2624 ret = INT_MAX;
2625 *MSVCRT__errno() = MSVCRT_ERANGE;
2626 } else if(ret < INT_MIN) {
2627 ret = INT_MIN;
2628 *MSVCRT__errno() = MSVCRT_ERANGE;
2630 return ret;
2633 /*********************************************************************
2634 * _wtoi (MSVCRT.@)
2636 int __cdecl MSVCRT__wtoi(const MSVCRT_wchar_t *str)
2638 return MSVCRT__wtoi_l(str, NULL);
2641 /*********************************************************************
2642 * _wtol_l (MSVCRT.@)
2644 MSVCRT_long __cdecl MSVCRT__wtol_l(const MSVCRT_wchar_t *str, MSVCRT__locale_t locale)
2646 __int64 ret = MSVCRT__wcstoi64_l(str, NULL, 10, locale);
2648 if(ret > MSVCRT_LONG_MAX) {
2649 ret = MSVCRT_LONG_MAX;
2650 *MSVCRT__errno() = MSVCRT_ERANGE;
2651 } else if(ret < MSVCRT_LONG_MIN) {
2652 ret = MSVCRT_LONG_MIN;
2653 *MSVCRT__errno() = MSVCRT_ERANGE;
2655 return ret;
2658 /*********************************************************************
2659 * _wtol (MSVCRT.@)
2661 MSVCRT_long __cdecl MSVCRT__wtol(const MSVCRT_wchar_t *str)
2663 return MSVCRT__wtol_l(str, NULL);
2666 #if _MSVCR_VER>=120
2668 /*********************************************************************
2669 * _wtoll_l (MSVCR120.@)
2671 MSVCRT_longlong __cdecl MSVCRT__wtoll_l(const MSVCRT_wchar_t *str, MSVCRT__locale_t locale)
2673 return MSVCRT__wcstoi64_l(str, NULL, 10, locale);
2676 /*********************************************************************
2677 * _wtoll (MSVCR120.@)
2679 MSVCRT_longlong __cdecl MSVCRT__wtoll(const MSVCRT_wchar_t *str)
2681 return MSVCRT__wtoll_l(str, NULL);
2684 #endif /* _MSVCR_VER>=120 */
2686 /*********************************************************************
2687 * _wcstoui64_l (MSVCRT.@)
2689 * FIXME: locale parameter is ignored
2691 unsigned __int64 CDECL MSVCRT__wcstoui64_l(const MSVCRT_wchar_t *nptr,
2692 MSVCRT_wchar_t **endptr, int base, MSVCRT__locale_t locale)
2694 BOOL negative = FALSE, empty = TRUE;
2695 unsigned __int64 ret = 0;
2697 TRACE("(%s %p %d %p)\n", debugstr_w(nptr), endptr, base, locale);
2699 if (!MSVCRT_CHECK_PMT(nptr != NULL)) return 0;
2700 if (!MSVCRT_CHECK_PMT(base == 0 || base >= 2)) return 0;
2701 if (!MSVCRT_CHECK_PMT(base <= 36)) return 0;
2703 if(endptr)
2704 *endptr = (MSVCRT_wchar_t*)nptr;
2706 while(MSVCRT__iswspace_l(*nptr, locale)) nptr++;
2708 if(*nptr == '-') {
2709 negative = TRUE;
2710 nptr++;
2711 } else if(*nptr == '+')
2712 nptr++;
2714 if((base==0 || base==16) && wctoint(*nptr, 1)==0 && (nptr[1]=='x' || nptr[1]=='X')) {
2715 base = 16;
2716 nptr += 2;
2719 if(base == 0) {
2720 if(wctoint(*nptr, 1)==0)
2721 base = 8;
2722 else
2723 base = 10;
2726 while(*nptr) {
2727 int v = wctoint(*nptr, base);
2728 if(v<0)
2729 break;
2731 nptr++;
2732 empty = FALSE;
2734 if(ret>MSVCRT_UI64_MAX/base || ret*base>MSVCRT_UI64_MAX-v) {
2735 ret = MSVCRT_UI64_MAX;
2736 *MSVCRT__errno() = MSVCRT_ERANGE;
2737 } else
2738 ret = ret*base + v;
2741 if(endptr && !empty)
2742 *endptr = (MSVCRT_wchar_t*)nptr;
2744 return negative ? -ret : ret;
2747 /*********************************************************************
2748 * _wcstoui64 (MSVCRT.@)
2750 unsigned __int64 CDECL MSVCRT__wcstoui64(const MSVCRT_wchar_t *nptr,
2751 MSVCRT_wchar_t **endptr, int base)
2753 return MSVCRT__wcstoui64_l(nptr, endptr, base, NULL);
2756 /*********************************************************************
2757 * _wcstoul_l (MSVCRT.@)
2759 MSVCRT_ulong __cdecl MSVCRT__wcstoul_l(const MSVCRT_wchar_t *s,
2760 MSVCRT_wchar_t **end, int base, MSVCRT__locale_t locale)
2762 __int64 ret = MSVCRT__wcstoi64_l(s, end, base, locale);
2764 if(ret > MSVCRT_ULONG_MAX) {
2765 ret = MSVCRT_ULONG_MAX;
2766 *MSVCRT__errno() = MSVCRT_ERANGE;
2767 }else if(ret < -(__int64)MSVCRT_ULONG_MAX) {
2768 ret = 1;
2769 *MSVCRT__errno() = MSVCRT_ERANGE;
2771 return ret;
2774 /*********************************************************************
2775 * wcstoul (MSVCRT.@)
2777 MSVCRT_ulong __cdecl MSVCRT_wcstoul(const MSVCRT_wchar_t *s, MSVCRT_wchar_t **end, int base)
2779 return MSVCRT__wcstoul_l(s, end, base, NULL);
2782 /******************************************************************
2783 * wcsnlen (MSVCRT.@)
2785 MSVCRT_size_t CDECL MSVCRT_wcsnlen(const MSVCRT_wchar_t *s, MSVCRT_size_t maxlen)
2787 MSVCRT_size_t i;
2789 for (i = 0; i < maxlen; i++)
2790 if (!s[i]) break;
2791 return i;
2794 /*********************************************************************
2795 * _towupper_l (MSVCRT.@)
2797 int CDECL MSVCRT__towupper_l(MSVCRT_wint_t c, MSVCRT__locale_t locale)
2799 MSVCRT_pthreadlocinfo locinfo;
2800 MSVCRT_wchar_t ret;
2802 if(!locale)
2803 locinfo = get_locinfo();
2804 else
2805 locinfo = locale->locinfo;
2807 if(!locinfo->lc_handle[MSVCRT_LC_CTYPE]) {
2808 if(c >= 'a' && c <= 'z')
2809 return c + 'A' - 'a';
2810 return c;
2813 if(!LCMapStringW(locinfo->lc_handle[MSVCRT_LC_CTYPE], LCMAP_UPPERCASE, &c, 1, &ret, 1))
2814 return c;
2815 return ret;
2818 /*********************************************************************
2819 * towupper (MSVCRT.@)
2821 int CDECL MSVCRT_towupper(MSVCRT_wint_t c)
2823 return MSVCRT__towupper_l(c, NULL);
2826 /*********************************************************************
2827 * wcschr (MSVCRT.@)
2829 MSVCRT_wchar_t* CDECL MSVCRT_wcschr(const MSVCRT_wchar_t *str, MSVCRT_wchar_t ch)
2831 do { if (*str == ch) return (WCHAR *)(ULONG_PTR)str; } while (*str++);
2832 return NULL;
2835 /*********************************************************************
2836 * wcsrchr (MSVCRT.@)
2838 MSVCRT_wchar_t* CDECL MSVCRT_wcsrchr(const MSVCRT_wchar_t *str, MSVCRT_wchar_t ch)
2840 WCHAR *ret = NULL;
2841 do { if (*str == ch) ret = (WCHAR *)(ULONG_PTR)str; } while (*str++);
2842 return ret;
2845 /***********************************************************************
2846 * wcslen (MSVCRT.@)
2848 MSVCRT_size_t CDECL MSVCRT_wcslen(const MSVCRT_wchar_t *str)
2850 const MSVCRT_wchar_t *s = str;
2851 while (*s) s++;
2852 return s - str;
2855 /*********************************************************************
2856 * wcsstr (MSVCRT.@)
2858 MSVCRT_wchar_t* CDECL MSVCRT_wcsstr(const MSVCRT_wchar_t *str, const MSVCRT_wchar_t *sub)
2860 while(*str)
2862 const MSVCRT_wchar_t *p1 = str, *p2 = sub;
2863 while(*p1 && *p2 && *p1 == *p2)
2865 p1++;
2866 p2++;
2868 if(!*p2)
2869 return (MSVCRT_wchar_t*)str;
2870 str++;
2872 return NULL;
2875 /*********************************************************************
2876 * _wtoi64_l (MSVCRT.@)
2878 __int64 CDECL MSVCRT__wtoi64_l(const MSVCRT_wchar_t *str, MSVCRT__locale_t locale)
2880 ULONGLONG RunningTotal = 0;
2881 BOOL bMinus = FALSE;
2883 while (MSVCRT__iswspace_l(*str, locale)) {
2884 str++;
2885 } /* while */
2887 if (*str == '+') {
2888 str++;
2889 } else if (*str == '-') {
2890 bMinus = TRUE;
2891 str++;
2892 } /* if */
2894 while (*str >= '0' && *str <= '9') {
2895 RunningTotal = RunningTotal * 10 + *str - '0';
2896 str++;
2897 } /* while */
2899 return bMinus ? -RunningTotal : RunningTotal;
2902 /*********************************************************************
2903 * _wtoi64 (MSVCRT.@)
2905 __int64 CDECL MSVCRT__wtoi64(const MSVCRT_wchar_t *str)
2907 return MSVCRT__wtoi64_l(str, NULL);
2910 /*********************************************************************
2911 * _wcsxfrm_l (MSVCRT.@)
2913 MSVCRT_size_t CDECL MSVCRT__wcsxfrm_l(MSVCRT_wchar_t *dest, const MSVCRT_wchar_t *src,
2914 MSVCRT_size_t len, MSVCRT__locale_t locale)
2916 MSVCRT_pthreadlocinfo locinfo;
2917 int i, ret;
2919 if(!MSVCRT_CHECK_PMT(src)) return INT_MAX;
2920 if(!MSVCRT_CHECK_PMT(dest || !len)) return INT_MAX;
2922 if(len > INT_MAX) {
2923 FIXME("len > INT_MAX not supported\n");
2924 len = INT_MAX;
2927 if(!locale)
2928 locinfo = get_locinfo();
2929 else
2930 locinfo = locale->locinfo;
2932 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE]) {
2933 MSVCRT_wcsncpy(dest, src, len);
2934 return MSVCRT_wcslen(src);
2937 ret = LCMapStringW(locinfo->lc_handle[MSVCRT_LC_COLLATE],
2938 LCMAP_SORTKEY, src, -1, NULL, 0);
2939 if(!ret) {
2940 if(len) dest[0] = 0;
2941 *MSVCRT__errno() = MSVCRT_EILSEQ;
2942 return INT_MAX;
2944 if(!len) return ret-1;
2946 if(ret > len) {
2947 dest[0] = 0;
2948 *MSVCRT__errno() = MSVCRT_ERANGE;
2949 return ret-1;
2952 ret = LCMapStringW(locinfo->lc_handle[MSVCRT_LC_COLLATE],
2953 LCMAP_SORTKEY, src, -1, dest, len) - 1;
2954 for(i=ret; i>=0; i--)
2955 dest[i] = ((unsigned char*)dest)[i];
2956 return ret;
2959 /*********************************************************************
2960 * wcsxfrm (MSVCRT.@)
2962 MSVCRT_size_t CDECL MSVCRT_wcsxfrm(MSVCRT_wchar_t *dest,
2963 const MSVCRT_wchar_t *src, MSVCRT_size_t len)
2965 return MSVCRT__wcsxfrm_l(dest, src, len, NULL);