gdiplus: Use wide-char string literals.
[wine.git] / dlls / msvcrt / wcs.c
blobfcadad7783258ff28be7523b830c6d4564842906
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
21 #include "config.h"
22 #include "wine/port.h"
24 #include <limits.h>
25 #include <stdio.h>
26 #include <math.h>
27 #include <assert.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 * _wcsicmp (MSVCRT.@)
144 INT CDECL MSVCRT__wcsicmp( const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2 )
146 return MSVCRT__wcsicmp_l(str1, str2, NULL);
149 /*********************************************************************
150 * _wcsnicmp_l (MSVCRT.@)
152 INT CDECL MSVCRT__wcsnicmp_l(const MSVCRT_wchar_t *str1, const MSVCRT_wchar_t *str2,
153 MSVCRT_size_t n, MSVCRT__locale_t locale)
155 MSVCRT__locale_tstruct tmp = {0};
156 MSVCRT_wchar_t c1, c2;
158 if (!n)
159 return 0;
161 if(!MSVCRT_CHECK_PMT(str1 != NULL) || !MSVCRT_CHECK_PMT(str2 != NULL))
162 return MSVCRT__NLSCMPERROR;
164 if(!locale)
165 locale = get_current_locale_noalloc(&tmp);
169 c1 = MSVCRT__towlower_l(*str1++, locale);
170 c2 = MSVCRT__towlower_l(*str2++, locale);
171 } while(--n && c1 && (c1 == c2));
173 free_locale_noalloc(&tmp);
174 return c1 - c2;
177 /*********************************************************************
178 * _wcsnicmp (MSVCRT.@)
180 INT CDECL MSVCRT__wcsnicmp(const MSVCRT_wchar_t *str1, const MSVCRT_wchar_t *str2, MSVCRT_size_t n)
182 return MSVCRT__wcsnicmp_l(str1, str2, n, NULL);
185 /*********************************************************************
186 * _wcsicoll_l (MSVCRT.@)
188 int CDECL MSVCRT__wcsicoll_l(const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2, MSVCRT__locale_t locale)
190 MSVCRT_pthreadlocinfo locinfo;
192 if(!locale)
193 locinfo = get_locinfo();
194 else
195 locinfo = locale->locinfo;
197 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE])
199 MSVCRT_wchar_t c1, c2;
203 c1 = *str1++;
204 if (c1 >= 'A' && c1 <= 'Z')
205 c1 += 'a' - 'A';
207 c2 = *str2++;
208 if (c2 >= 'A' && c2 <= 'Z')
209 c2 += 'a' - 'A';
210 } while(c1 && (c1 == c2));
211 return c1 - c2;
214 return CompareStringW(locinfo->lc_handle[MSVCRT_LC_COLLATE], NORM_IGNORECASE,
215 str1, -1, str2, -1)-CSTR_EQUAL;
218 /*********************************************************************
219 * _wcsicoll (MSVCRT.@)
221 INT CDECL MSVCRT__wcsicoll( const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2 )
223 return MSVCRT__wcsicoll_l(str1, str2, NULL);
226 /*********************************************************************
227 * _wcsnicoll_l (MSVCRT.@)
229 int CDECL MSVCRT__wcsnicoll_l(const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2,
230 MSVCRT_size_t count, MSVCRT__locale_t locale)
232 MSVCRT_pthreadlocinfo locinfo;
234 if(!locale)
235 locinfo = get_locinfo();
236 else
237 locinfo = locale->locinfo;
239 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE])
241 MSVCRT_wchar_t c1, c2;
243 if (!count)
244 return 0;
248 c1 = *str1++;
249 if (c1 >= 'A' && c1 <= 'Z')
250 c1 += 'a' - 'A';
252 c2 = *str2++;
253 if (c2 >= 'A' && c2 <= 'Z')
254 c2 += 'a' - 'A';
255 } while(--count && c1 && (c1 == c2));
256 return c1 - c2;
259 return CompareStringW(locinfo->lc_handle[MSVCRT_LC_COLLATE], NORM_IGNORECASE,
260 str1, MSVCRT_wcsnlen(str1, count),
261 str2, MSVCRT_wcsnlen(str2, count))-CSTR_EQUAL;
264 /*********************************************************************
265 * _wcsnicoll (MSVCRT.@)
267 INT CDECL MSVCRT__wcsnicoll( const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2, MSVCRT_size_t count )
269 return MSVCRT__wcsnicoll_l(str1, str2, count, NULL);
272 /*********************************************************************
273 * _wcsnset (MSVCRT.@)
275 MSVCRT_wchar_t* CDECL MSVCRT__wcsnset( MSVCRT_wchar_t* str, MSVCRT_wchar_t c, MSVCRT_size_t n )
277 MSVCRT_wchar_t* ret = str;
278 while ((n-- > 0) && *str) *str++ = c;
279 return ret;
282 /*********************************************************************
283 * _wcsnset_s (MSVCRT.@)
285 int CDECL MSVCRT__wcsnset_s( MSVCRT_wchar_t *str, MSVCRT_size_t size, MSVCRT_wchar_t c, MSVCRT_size_t count )
287 MSVCRT_size_t i;
289 if(!str && !size && !count) return 0;
290 if(!MSVCRT_CHECK_PMT(str != NULL)) return MSVCRT_EINVAL;
291 if(!MSVCRT_CHECK_PMT(size > 0)) return MSVCRT_EINVAL;
293 for(i=0; i<size-1 && i<count; i++) {
294 if(!str[i]) return 0;
295 str[i] = c;
297 for(; i<size; i++)
298 if(!str[i]) return 0;
300 str[0] = 0;
301 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
302 *MSVCRT__errno() = MSVCRT_EINVAL;
303 return MSVCRT_EINVAL;
306 /*********************************************************************
307 * _wcsrev (MSVCRT.@)
309 MSVCRT_wchar_t* CDECL MSVCRT__wcsrev( MSVCRT_wchar_t* str )
311 MSVCRT_wchar_t* ret = str;
312 MSVCRT_wchar_t* end = str + MSVCRT_wcslen(str) - 1;
313 while (end > str)
315 MSVCRT_wchar_t t = *end;
316 *end-- = *str;
317 *str++ = t;
319 return ret;
322 /*********************************************************************
323 * _wcsset_s (MSVCRT.@)
325 int CDECL MSVCRT__wcsset_s( MSVCRT_wchar_t *str, MSVCRT_size_t n, MSVCRT_wchar_t c )
327 MSVCRT_wchar_t *p = str;
329 if(!MSVCRT_CHECK_PMT(str != NULL)) return MSVCRT_EINVAL;
330 if(!MSVCRT_CHECK_PMT(n)) return MSVCRT_EINVAL;
332 while(*p && --n) *p++ = c;
333 if(!n) {
334 str[0] = 0;
335 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
336 *MSVCRT__errno() = MSVCRT_EINVAL;
337 return MSVCRT_EINVAL;
339 return 0;
342 /*********************************************************************
343 * _wcsset (MSVCRT.@)
345 MSVCRT_wchar_t* CDECL MSVCRT__wcsset( MSVCRT_wchar_t* str, MSVCRT_wchar_t c )
347 MSVCRT_wchar_t* ret = str;
348 while (*str) *str++ = c;
349 return ret;
352 /******************************************************************
353 * _wcsupr_s_l (MSVCRT.@)
355 int CDECL MSVCRT__wcsupr_s_l( MSVCRT_wchar_t* str, MSVCRT_size_t n,
356 MSVCRT__locale_t locale )
358 MSVCRT__locale_tstruct tmp = {0};
359 MSVCRT_wchar_t* ptr = str;
361 if (!str || !n)
363 if (str) *str = '\0';
364 *MSVCRT__errno() = MSVCRT_EINVAL;
365 return MSVCRT_EINVAL;
368 if(!locale)
369 locale = get_current_locale_noalloc(&tmp);
371 while (n--)
373 if (!*ptr)
375 free_locale_noalloc(&tmp);
376 return 0;
378 *ptr = MSVCRT__towupper_l(*ptr, locale);
379 ptr++;
382 free_locale_noalloc(&tmp);
384 /* MSDN claims that the function should return and set errno to
385 * ERANGE, which doesn't seem to be true based on the tests. */
386 *str = '\0';
387 *MSVCRT__errno() = MSVCRT_EINVAL;
388 return MSVCRT_EINVAL;
391 /******************************************************************
392 * _wcsupr_s (MSVCRT.@)
395 INT CDECL MSVCRT__wcsupr_s( MSVCRT_wchar_t* str, MSVCRT_size_t n )
397 return MSVCRT__wcsupr_s_l( str, n, NULL );
400 /******************************************************************
401 * _wcsupr_l (MSVCRT.@)
403 MSVCRT_wchar_t* CDECL MSVCRT__wcsupr_l( MSVCRT_wchar_t *str, MSVCRT__locale_t locale )
405 MSVCRT__wcsupr_s_l( str, -1, locale);
406 return str;
409 /******************************************************************
410 * _wcsupr (MSVCRT.@)
412 MSVCRT_wchar_t* CDECL MSVCRT__wcsupr( MSVCRT_wchar_t *str )
414 return MSVCRT__wcsupr_l(str, NULL);
417 /******************************************************************
418 * _wcslwr_s_l (MSVCRT.@)
420 int CDECL MSVCRT__wcslwr_s_l( MSVCRT_wchar_t* str, MSVCRT_size_t n, MSVCRT__locale_t locale )
422 MSVCRT__locale_tstruct tmp = {0};
423 MSVCRT_wchar_t* ptr = str;
425 if (!str || !n)
427 if (str) *str = '\0';
428 *MSVCRT__errno() = MSVCRT_EINVAL;
429 return MSVCRT_EINVAL;
432 if(!locale)
433 locale = get_current_locale_noalloc(&tmp);
435 while (n--)
437 if (!*ptr)
439 free_locale_noalloc(&tmp);
440 return 0;
442 *ptr = MSVCRT__towlower_l(*ptr, locale);
443 ptr++;
446 free_locale_noalloc(&tmp);
448 /* MSDN claims that the function should return and set errno to
449 * ERANGE, which doesn't seem to be true based on the tests. */
450 *str = '\0';
451 *MSVCRT__errno() = MSVCRT_EINVAL;
452 return MSVCRT_EINVAL;
455 /******************************************************************
456 * _wcslwr_s (MSVCRT.@)
458 int CDECL MSVCRT__wcslwr_s( MSVCRT_wchar_t* str, MSVCRT_size_t n )
460 return MSVCRT__wcslwr_s_l(str, n, NULL);
463 /******************************************************************
464 * _wcslwr_l (MSVCRT.@)
466 MSVCRT_wchar_t* CDECL MSVCRT__wcslwr_l( MSVCRT_wchar_t* str, MSVCRT__locale_t locale )
468 MSVCRT__wcslwr_s_l(str, -1, locale);
469 return str;
472 /******************************************************************
473 * _wcslwr (MSVCRT.@)
475 MSVCRT_wchar_t* CDECL MSVCRT__wcslwr( MSVCRT_wchar_t* str )
477 MSVCRT__wcslwr_s_l(str, -1, NULL);
478 return str;
481 /*********************************************************************
482 * wcsncmp (MSVCRT.@)
484 int CDECL MSVCRT_wcsncmp(const MSVCRT_wchar_t *str1, const MSVCRT_wchar_t *str2, MSVCRT_size_t n)
486 if (!n)
487 return 0;
488 while(--n && *str1 && (*str1 == *str2))
490 str1++;
491 str2++;
493 return *str1 - *str2;
496 /*********************************************************************
497 * _wcsncoll_l (MSVCRT.@)
499 int CDECL MSVCRT__wcsncoll_l(const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2,
500 MSVCRT_size_t count, MSVCRT__locale_t locale)
502 MSVCRT_pthreadlocinfo locinfo;
504 if(!locale)
505 locinfo = get_locinfo();
506 else
507 locinfo = locale->locinfo;
509 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE])
510 return MSVCRT_wcsncmp(str1, str2, count);
511 return CompareStringW(locinfo->lc_handle[MSVCRT_LC_COLLATE], 0,
512 str1, MSVCRT_wcsnlen(str1, count),
513 str2, MSVCRT_wcsnlen(str2, count))-CSTR_EQUAL;
516 /*********************************************************************
517 * _wcsncoll (MSVCRT.@)
519 int CDECL MSVCRT__wcsncoll(const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2, MSVCRT_size_t count)
521 return MSVCRT__wcsncoll_l(str1, str2, count, NULL);
524 static MSVCRT_wchar_t strtod_wstr_get(void *ctx)
526 const MSVCRT_wchar_t **p = ctx;
527 if (!**p) return MSVCRT_WEOF;
528 return *(*p)++;
531 static void strtod_wstr_unget(void *ctx)
533 const MSVCRT_wchar_t **p = ctx;
534 (*p)--;
537 /*********************************************************************
538 * _wcstod_l (MSVCRT.@)
540 double CDECL MSVCRT__wcstod_l(const MSVCRT_wchar_t* str, MSVCRT_wchar_t** end,
541 MSVCRT__locale_t locale)
543 MSVCRT_pthreadlocinfo locinfo;
544 const MSVCRT_wchar_t *beg, *p;
545 struct fpnum fp;
546 double ret;
547 int err;
549 if (!MSVCRT_CHECK_PMT(str != NULL)) {
550 if (end) *end = NULL;
551 return 0;
554 if (!locale)
555 locinfo = get_locinfo();
556 else
557 locinfo = locale->locinfo;
559 p = str;
560 while(MSVCRT__iswspace_l(*p, locale))
561 p++;
562 beg = p;
564 fp = fpnum_parse(strtod_wstr_get, strtod_wstr_unget, &p, locinfo, FALSE);
565 if (end) *end = (p == beg ? (MSVCRT_wchar_t*)str : (MSVCRT_wchar_t*)p);
567 err = fpnum_double(&fp, &ret);
568 if(err) *MSVCRT__errno() = err;
569 return ret;
572 /*********************************************************************
573 * wcsrtombs_l (INTERNAL)
575 static MSVCRT_size_t MSVCRT_wcsrtombs_l(char *mbstr, const MSVCRT_wchar_t **wcstr,
576 MSVCRT_size_t count, MSVCRT__locale_t locale)
578 MSVCRT_pthreadlocinfo locinfo;
579 MSVCRT_size_t tmp = 0;
580 BOOL used_default = FALSE;
581 BOOL *pused_default;
583 if(!locale)
584 locinfo = get_locinfo();
585 else
586 locinfo = locale->locinfo;
588 if(!locinfo->lc_codepage) {
589 MSVCRT_size_t i;
591 if(!mbstr)
592 return MSVCRT_wcslen(*wcstr);
594 for(i=0; i<count; i++) {
595 if((*wcstr)[i] > 255) {
596 *MSVCRT__errno() = MSVCRT_EILSEQ;
597 return -1;
600 mbstr[i] = (*wcstr)[i];
601 if(!(*wcstr)[i]) break;
603 return i;
606 pused_default = (locinfo->lc_codepage != CP_UTF8 ? &used_default : NULL);
608 if(!mbstr) {
609 tmp = WideCharToMultiByte(locinfo->lc_codepage, WC_NO_BEST_FIT_CHARS,
610 *wcstr, -1, NULL, 0, NULL, pused_default);
611 if(!tmp || used_default) {
612 *MSVCRT__errno() = MSVCRT_EILSEQ;
613 return -1;
615 return tmp-1;
618 while(**wcstr) {
619 char buf[3];
620 MSVCRT_size_t i, size;
622 size = WideCharToMultiByte(locinfo->lc_codepage, WC_NO_BEST_FIT_CHARS,
623 *wcstr, 1, buf, 3, NULL, pused_default);
624 if(!size || used_default) {
625 *MSVCRT__errno() = MSVCRT_EILSEQ;
626 return -1;
628 if(tmp+size > count)
629 return tmp;
631 for(i=0; i<size; i++)
632 mbstr[tmp++] = buf[i];
633 (*wcstr)++;
636 if(tmp < count) {
637 mbstr[tmp] = '\0';
638 *wcstr = NULL;
640 return tmp;
643 /*********************************************************************
644 * _wcstombs_l (MSVCRT.@)
646 MSVCRT_size_t CDECL MSVCRT__wcstombs_l(char *mbstr, const MSVCRT_wchar_t *wcstr,
647 MSVCRT_size_t count, MSVCRT__locale_t locale)
649 return MSVCRT_wcsrtombs_l(mbstr, &wcstr, count, locale);
652 /*********************************************************************
653 * wcstombs (MSVCRT.@)
655 MSVCRT_size_t CDECL MSVCRT_wcstombs(char *mbstr, const MSVCRT_wchar_t *wcstr,
656 MSVCRT_size_t count)
658 return MSVCRT_wcsrtombs_l(mbstr, &wcstr, count, NULL);
661 /*********************************************************************
662 * wcsrtombs (MSVCRT.@)
664 MSVCRT_size_t CDECL MSVCRT_wcsrtombs(char *mbstr, const MSVCRT_wchar_t **wcstr,
665 MSVCRT_size_t count, MSVCRT_mbstate_t *mbstate)
667 if(mbstate)
668 *mbstate = 0;
670 return MSVCRT_wcsrtombs_l(mbstr, wcstr, count, NULL);
673 /*********************************************************************
674 * MSVCRT_wcsrtombs_s_l (INTERNAL)
676 static int MSVCRT_wcsrtombs_s_l(MSVCRT_size_t *ret, char *mbstr,
677 MSVCRT_size_t size, const MSVCRT_wchar_t **wcstr,
678 MSVCRT_size_t count, MSVCRT__locale_t locale)
680 MSVCRT_size_t conv;
681 int err;
683 if(!mbstr && !size && wcstr) {
684 conv = MSVCRT_wcsrtombs_l(NULL, wcstr, 0, locale);
685 if(ret)
686 *ret = conv+1;
687 if(conv == -1)
688 return *MSVCRT__errno();
689 return 0;
692 if (!MSVCRT_CHECK_PMT(mbstr != NULL)) return MSVCRT_EINVAL;
693 if (size) mbstr[0] = '\0';
694 if (!MSVCRT_CHECK_PMT(wcstr != NULL)) return MSVCRT_EINVAL;
695 if (!MSVCRT_CHECK_PMT(*wcstr != NULL)) return MSVCRT_EINVAL;
697 if(count==MSVCRT__TRUNCATE || size<count)
698 conv = size;
699 else
700 conv = count;
702 err = 0;
703 conv = MSVCRT_wcsrtombs_l(mbstr, wcstr, conv, locale);
704 if(conv == -1) {
705 conv = 0;
706 if(size)
707 mbstr[0] = '\0';
708 err = *MSVCRT__errno();
709 }else if(conv < size)
710 mbstr[conv++] = '\0';
711 else if(conv==size && (count==MSVCRT__TRUNCATE || mbstr[conv-1]=='\0')) {
712 mbstr[conv-1] = '\0';
713 if(count==MSVCRT__TRUNCATE)
714 err = MSVCRT_STRUNCATE;
715 }else {
716 MSVCRT_INVALID_PMT("mbstr[size] is too small", MSVCRT_ERANGE);
717 conv = 0;
718 if(size)
719 mbstr[0] = '\0';
720 err = MSVCRT_ERANGE;
723 if(ret)
724 *ret = conv;
725 return err;
728 /*********************************************************************
729 * _wcstombs_s_l (MSVCRT.@)
731 int CDECL MSVCRT__wcstombs_s_l(MSVCRT_size_t *ret, char *mbstr,
732 MSVCRT_size_t size, const MSVCRT_wchar_t *wcstr,
733 MSVCRT_size_t count, MSVCRT__locale_t locale)
735 return MSVCRT_wcsrtombs_s_l(ret, mbstr, size, &wcstr,count, locale);
738 /*********************************************************************
739 * wcstombs_s (MSVCRT.@)
741 int CDECL MSVCRT_wcstombs_s(MSVCRT_size_t *ret, char *mbstr,
742 MSVCRT_size_t size, const MSVCRT_wchar_t *wcstr, MSVCRT_size_t count)
744 return MSVCRT_wcsrtombs_s_l(ret, mbstr, size, &wcstr, count, NULL);
747 /*********************************************************************
748 * wcsrtombs_s (MSVCRT.@)
750 int CDECL MSVCRT_wcsrtombs_s(MSVCRT_size_t *ret, char *mbstr, MSVCRT_size_t size,
751 const MSVCRT_wchar_t **wcstr, MSVCRT_size_t count, MSVCRT_mbstate_t *mbstate)
753 if(mbstate)
754 *mbstate = 0;
756 return MSVCRT_wcsrtombs_s_l(ret, mbstr, size, wcstr, count, NULL);
759 /*********************************************************************
760 * wcstod (MSVCRT.@)
762 double CDECL MSVCRT_wcstod(const MSVCRT_wchar_t* lpszStr, MSVCRT_wchar_t** end)
764 return MSVCRT__wcstod_l(lpszStr, end, NULL);
767 /*********************************************************************
768 * _wtof (MSVCRT.@)
770 double CDECL MSVCRT__wtof(const MSVCRT_wchar_t *str)
772 return MSVCRT__wcstod_l(str, NULL, NULL);
775 /*********************************************************************
776 * _wtof_l (MSVCRT.@)
778 double CDECL MSVCRT__wtof_l(const MSVCRT_wchar_t *str, MSVCRT__locale_t locale)
780 return MSVCRT__wcstod_l(str, NULL, locale);
783 #if _MSVCR_VER>=120
785 /*********************************************************************
786 * _wcstof_l (MSVCR120.@)
788 float CDECL MSVCRT__wcstof_l( const MSVCRT_wchar_t *str, MSVCRT_wchar_t **end, MSVCRT__locale_t locale )
790 return MSVCRT__wcstod_l(str, end, locale);
793 /*********************************************************************
794 * wcstof (MSVCR120.@)
796 float CDECL MSVCRT_wcstof( const MSVCRT_wchar_t *str, MSVCRT_wchar_t **end )
798 return MSVCRT__wcstof_l(str, end, NULL);
801 #endif /* _MSVCR_VER>=120 */
803 /*********************************************************************
804 * arg_clbk_valist (INTERNAL)
806 printf_arg arg_clbk_valist(void *ctx, int arg_pos, int type, __ms_va_list *valist)
808 printf_arg ret;
810 if(type == VT_I8)
811 ret.get_longlong = va_arg(*valist, LONGLONG);
812 else if(type == VT_INT)
813 ret.get_int = va_arg(*valist, int);
814 else if(type == VT_R8)
815 ret.get_double = va_arg(*valist, double);
816 else if(type == VT_PTR)
817 ret.get_ptr = va_arg(*valist, void*);
818 else {
819 ERR("Incorrect type\n");
820 ret.get_int = 0;
823 return ret;
826 /*********************************************************************
827 * arg_clbk_positional (INTERNAL)
829 printf_arg arg_clbk_positional(void *ctx, int pos, int type, __ms_va_list *valist)
831 printf_arg *args = ctx;
832 return args[pos];
835 /*********************************************************************
836 * _vsnprintf (MSVCRT.@)
838 int CDECL MSVCRT_vsnprintf( char *str, MSVCRT_size_t len,
839 const char *format, __ms_va_list valist )
841 static const char nullbyte = '\0';
842 struct _str_ctx_a ctx = {len, str};
843 int ret;
845 ret = pf_printf_a(puts_clbk_str_a, &ctx, format, NULL, 0,
846 arg_clbk_valist, NULL, &valist);
847 puts_clbk_str_a(&ctx, 1, &nullbyte);
848 return ret;
851 #if _MSVCR_VER>=140
853 static int puts_clbk_str_c99_a(void *ctx, int len, const char *str)
855 struct _str_ctx_a *out = ctx;
857 if(!out->buf)
858 return len;
860 if(out->len < len) {
861 memmove(out->buf, str, out->len);
862 out->buf += out->len;
863 out->len = 0;
864 return len;
867 memmove(out->buf, str, len);
868 out->buf += len;
869 out->len -= len;
870 return len;
873 /*********************************************************************
874 * __stdio_common_vsprintf (UCRTBASE.@)
876 int CDECL MSVCRT__stdio_common_vsprintf( unsigned __int64 options, char *str, MSVCRT_size_t len, const char *format,
877 MSVCRT__locale_t locale, __ms_va_list valist )
879 static const char nullbyte = '\0';
880 struct _str_ctx_a ctx = {len, str};
881 int ret;
883 if (options & ~UCRTBASE_PRINTF_MASK)
884 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
885 ret = pf_printf_a(puts_clbk_str_c99_a,
886 &ctx, format, locale, options & UCRTBASE_PRINTF_MASK, arg_clbk_valist, NULL, &valist);
887 puts_clbk_str_a(&ctx, 1, &nullbyte);
889 if(!str)
890 return ret;
891 if(options & UCRTBASE_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION)
892 return ret>len ? -1 : ret;
893 if(ret>=len) {
894 if(len) str[len-1] = 0;
895 if(options & UCRTBASE_PRINTF_STANDARD_SNPRINTF_BEHAVIOUR)
896 return ret;
897 return len > 0 ? -2 : -1;
899 return ret;
902 #endif /* _MSVCR_VER>=140 */
904 /*********************************************************************
905 * _vsnprintf_l (MSVCRT.@)
907 int CDECL MSVCRT_vsnprintf_l( char *str, MSVCRT_size_t len, const char *format,
908 MSVCRT__locale_t locale, __ms_va_list valist )
910 static const char nullbyte = '\0';
911 struct _str_ctx_a ctx = {len, str};
912 int ret;
914 ret = pf_printf_a(puts_clbk_str_a, &ctx, format, locale, 0,
915 arg_clbk_valist, NULL, &valist);
916 puts_clbk_str_a(&ctx, 1, &nullbyte);
917 return ret;
920 /*********************************************************************
921 * _vsprintf_l (MSVCRT.@)
923 int CDECL MSVCRT_vsprintf_l( char *str, const char *format,
924 MSVCRT__locale_t locale, __ms_va_list valist )
926 return MSVCRT_vsnprintf_l(str, INT_MAX, format, locale, valist);
929 /*********************************************************************
930 * _sprintf_l (MSVCRT.@)
932 int WINAPIV MSVCRT_sprintf_l(char *str, const char *format,
933 MSVCRT__locale_t locale, ...)
935 int retval;
936 __ms_va_list valist;
937 __ms_va_start(valist, locale);
938 retval = MSVCRT_vsnprintf_l(str, INT_MAX, format, locale, valist);
939 __ms_va_end(valist);
940 return retval;
943 static int CDECL MSVCRT_vsnprintf_s_l_opt( char *str, MSVCRT_size_t sizeOfBuffer,
944 MSVCRT_size_t count, const char *format, DWORD options,
945 MSVCRT__locale_t locale, __ms_va_list valist )
947 static const char nullbyte = '\0';
948 struct _str_ctx_a ctx;
949 int len, ret;
951 if(sizeOfBuffer<count+1 || count==-1)
952 len = sizeOfBuffer;
953 else
954 len = count+1;
956 ctx.len = len;
957 ctx.buf = str;
958 ret = pf_printf_a(puts_clbk_str_a, &ctx, format, locale, MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
959 arg_clbk_valist, NULL, &valist);
960 puts_clbk_str_a(&ctx, 1, &nullbyte);
962 if(ret<0 || ret==len) {
963 if(count!=MSVCRT__TRUNCATE && count>sizeOfBuffer) {
964 MSVCRT_INVALID_PMT("str[sizeOfBuffer] is too small", MSVCRT_ERANGE);
965 memset(str, 0, sizeOfBuffer);
966 } else
967 str[len-1] = '\0';
969 return -1;
972 return ret;
975 static int MSVCRT_vsnwprintf_s_l_opt( MSVCRT_wchar_t *str, MSVCRT_size_t sizeOfBuffer,
976 MSVCRT_size_t count, const MSVCRT_wchar_t *format, DWORD options,
977 MSVCRT__locale_t locale, __ms_va_list valist)
979 static const MSVCRT_wchar_t nullbyte = '\0';
980 struct _str_ctx_w ctx;
981 int len, ret;
983 len = sizeOfBuffer;
984 if(count!=-1 && len>count+1)
985 len = count+1;
987 ctx.len = len;
988 ctx.buf = str;
989 ret = pf_printf_w(puts_clbk_str_w, &ctx, format, locale, MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
990 arg_clbk_valist, NULL, &valist);
991 puts_clbk_str_w(&ctx, 1, &nullbyte);
993 if(ret<0 || ret==len) {
994 if(count!=MSVCRT__TRUNCATE && count>sizeOfBuffer) {
995 MSVCRT_INVALID_PMT("str[sizeOfBuffer] is too small", MSVCRT_ERANGE);
996 memset(str, 0, sizeOfBuffer*sizeof(MSVCRT_wchar_t));
997 } else
998 str[len-1] = '\0';
1000 return -1;
1003 return ret;
1006 /*********************************************************************
1007 * _vsnprintf_s_l (MSVCRT.@)
1009 int CDECL MSVCRT_vsnprintf_s_l( char *str, MSVCRT_size_t sizeOfBuffer,
1010 MSVCRT_size_t count, const char *format,
1011 MSVCRT__locale_t locale, __ms_va_list valist )
1013 return MSVCRT_vsnprintf_s_l_opt(str, sizeOfBuffer, count, format, 0, locale, valist);
1016 /*********************************************************************
1017 * _vsprintf_s_l (MSVCRT.@)
1019 int CDECL MSVCRT_vsprintf_s_l( char *str, MSVCRT_size_t count, const char *format,
1020 MSVCRT__locale_t locale, __ms_va_list valist )
1022 return MSVCRT_vsnprintf_s_l(str, INT_MAX, count, format, locale, valist);
1025 /*********************************************************************
1026 * _sprintf_s_l (MSVCRT.@)
1028 int WINAPIV MSVCRT_sprintf_s_l( char *str, MSVCRT_size_t count, const char *format,
1029 MSVCRT__locale_t locale, ...)
1031 int retval;
1032 __ms_va_list valist;
1033 __ms_va_start(valist, locale);
1034 retval = MSVCRT_vsnprintf_s_l(str, INT_MAX, count, format, locale, valist);
1035 __ms_va_end(valist);
1036 return retval;
1039 /*********************************************************************
1040 * _vsnprintf_s (MSVCRT.@)
1042 int CDECL MSVCRT_vsnprintf_s( char *str, MSVCRT_size_t sizeOfBuffer,
1043 MSVCRT_size_t count, const char *format, __ms_va_list valist )
1045 return MSVCRT_vsnprintf_s_l(str,sizeOfBuffer, count, format, NULL, valist);
1048 /*********************************************************************
1049 * _vsnprintf_c_l (MSVCRT.@)
1051 int CDECL MSVCRT_vsnprintf_c_l(char *str, MSVCRT_size_t len, const char *format,
1052 MSVCRT__locale_t locale, __ms_va_list valist)
1054 return MSVCRT_vsnprintf_s_l_opt(str, len, len, format, 0, locale, valist);
1057 /*********************************************************************
1058 * _vsnprintf_c (MSVCRT.@)
1060 int CDECL MSVCRT_vsnprintf_c(char *str, MSVCRT_size_t len,
1061 const char *format, __ms_va_list valist)
1063 return MSVCRT_vsnprintf_c_l(str, len, format, NULL, valist);
1066 #if _MSVCR_VER>=140
1068 /*********************************************************************
1069 * __stdio_common_vsnprintf_s (UCRTBASE.@)
1071 int CDECL MSVCRT__stdio_common_vsnprintf_s( unsigned __int64 options,
1072 char *str, MSVCRT_size_t sizeOfBuffer, MSVCRT_size_t count,
1073 const char *format, MSVCRT__locale_t locale, __ms_va_list valist )
1075 if (options & ~UCRTBASE_PRINTF_MASK)
1076 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
1077 return MSVCRT_vsnprintf_s_l_opt(str, sizeOfBuffer, count, format, options & UCRTBASE_PRINTF_MASK, locale, valist);
1080 /*********************************************************************
1081 * __stdio_common_vsnwprintf_s (UCRTBASE.@)
1083 int CDECL MSVCRT__stdio_common_vsnwprintf_s( unsigned __int64 options,
1084 MSVCRT_wchar_t *str, MSVCRT_size_t sizeOfBuffer, MSVCRT_size_t count,
1085 const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, __ms_va_list valist )
1087 if (options & ~UCRTBASE_PRINTF_MASK)
1088 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
1089 return MSVCRT_vsnwprintf_s_l_opt(str, sizeOfBuffer, count, format, options & UCRTBASE_PRINTF_MASK, locale, valist);
1092 /*********************************************************************
1093 * __stdio_common_vswprintf_s (UCRTBASE.@)
1095 int CDECL MSVCRT__stdio_common_vswprintf_s( unsigned __int64 options,
1096 MSVCRT_wchar_t *str, MSVCRT_size_t count, const MSVCRT_wchar_t *format,
1097 MSVCRT__locale_t locale, __ms_va_list valist )
1099 return MSVCRT__stdio_common_vsnwprintf_s(options, str, INT_MAX, count, format, locale, valist);
1102 /*********************************************************************
1103 * __stdio_common_vsprintf_s (UCRTBASE.@)
1105 int CDECL MSVCRT__stdio_common_vsprintf_s( unsigned __int64 options,
1106 char *str, MSVCRT_size_t count, const char *format,
1107 MSVCRT__locale_t locale, __ms_va_list valist )
1109 if (options & ~UCRTBASE_PRINTF_MASK)
1110 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
1111 return MSVCRT_vsnprintf_s_l_opt(str, INT_MAX, count, format, options & UCRTBASE_PRINTF_MASK, locale, valist);
1114 #endif /* _MSVCR_VER>=140 */
1116 /*********************************************************************
1117 * vsprintf (MSVCRT.@)
1119 int CDECL MSVCRT_vsprintf( char *str, const char *format, __ms_va_list valist)
1121 return MSVCRT_vsnprintf(str, INT_MAX, format, valist);
1124 /*********************************************************************
1125 * vsprintf_s (MSVCRT.@)
1127 int CDECL MSVCRT_vsprintf_s( char *str, MSVCRT_size_t num, const char *format, __ms_va_list valist)
1129 return MSVCRT_vsnprintf(str, num, format, valist);
1132 /*********************************************************************
1133 * _vscprintf (MSVCRT.@)
1135 int CDECL MSVCRT__vscprintf( const char *format, __ms_va_list valist )
1137 return MSVCRT_vsnprintf( NULL, INT_MAX, format, valist );
1140 /*********************************************************************
1141 * _vscprintf_l (MSVCRT.@)
1143 int CDECL MSVCRT__vscprintf_l(const char *format,
1144 MSVCRT__locale_t locale, __ms_va_list valist)
1146 return MSVCRT_vsnprintf_l(NULL, INT_MAX, format, locale, valist);
1149 /*********************************************************************
1150 * _vscprintf_p_l (MSVCRT.@)
1152 int CDECL MSVCRT__vscprintf_p_l(const char *format,
1153 MSVCRT__locale_t locale, __ms_va_list args)
1155 printf_arg args_ctx[MSVCRT__ARGMAX+1];
1156 struct _str_ctx_a puts_ctx = {INT_MAX, NULL};
1157 int ret;
1159 memset(args_ctx, 0, sizeof(args_ctx));
1161 ret = create_positional_ctx_a(args_ctx, format, args);
1162 if(ret < 0) {
1163 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
1164 *MSVCRT__errno() = MSVCRT_EINVAL;
1165 return ret;
1166 } else if(ret == 0) {
1167 ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale,
1168 MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER,
1169 arg_clbk_valist, NULL, &args);
1170 } else {
1171 ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale,
1172 MSVCRT_PRINTF_POSITIONAL_PARAMS | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER,
1173 arg_clbk_positional, args_ctx, NULL);
1176 return ret;
1179 /*********************************************************************
1180 * _vscprintf_p (MSVCR80.@)
1182 int CDECL MSVCRT__vscprintf_p(const char *format, __ms_va_list argptr)
1184 return MSVCRT__vscprintf_p_l(format, NULL, argptr);
1187 /*********************************************************************
1188 * _snprintf (MSVCRT.@)
1190 int WINAPIV MSVCRT__snprintf(char *str, MSVCRT_size_t len, const char *format, ...)
1192 int retval;
1193 __ms_va_list valist;
1194 __ms_va_start(valist, format);
1195 retval = MSVCRT_vsnprintf(str, len, format, valist);
1196 __ms_va_end(valist);
1197 return retval;
1200 /*********************************************************************
1201 * _snprintf_l (MSVCRT.@)
1203 int WINAPIV MSVCRT__snprintf_l(char *str, MSVCRT_size_t count, const char *format,
1204 MSVCRT__locale_t locale, ...)
1206 int retval;
1207 __ms_va_list valist;
1208 __ms_va_start(valist, locale);
1209 retval = MSVCRT_vsnprintf_l(str, count, format, locale, valist);
1210 __ms_va_end(valist);
1211 return retval;
1214 /*********************************************************************
1215 * _snprintf_c_l (MSVCRT.@)
1217 int WINAPIV MSVCRT_snprintf_c_l(char *str, MSVCRT_size_t count, const char *format,
1218 MSVCRT__locale_t locale, ...)
1220 int retval;
1221 __ms_va_list valist;
1222 __ms_va_start(valist, locale);
1223 retval = MSVCRT_vsnprintf_c_l(str, count, format, locale, valist);
1224 __ms_va_end(valist);
1225 return retval;
1228 /*********************************************************************
1229 * _snprintf_c (MSVCRT.@)
1231 int WINAPIV MSVCRT_snprintf_c(char *str, MSVCRT_size_t count, const char *format, ...)
1233 int retval;
1234 __ms_va_list valist;
1235 __ms_va_start(valist, format);
1236 retval = MSVCRT_vsnprintf_c(str, count, format, valist);
1237 __ms_va_end(valist);
1238 return retval;
1241 /*********************************************************************
1242 * _snprintf_s_l (MSVCRT.@)
1244 int WINAPIV MSVCRT_snprintf_s_l(char *str, MSVCRT_size_t len, MSVCRT_size_t count,
1245 const char *format, MSVCRT__locale_t locale, ...)
1247 int retval;
1248 __ms_va_list valist;
1249 __ms_va_start(valist, locale);
1250 retval = MSVCRT_vsnprintf_s_l(str, len, count, format, locale, valist);
1251 __ms_va_end(valist);
1252 return retval;
1255 /*********************************************************************
1256 * _snprintf_s (MSVCRT.@)
1258 int WINAPIV MSVCRT__snprintf_s(char *str, MSVCRT_size_t len, MSVCRT_size_t count,
1259 const char *format, ...)
1261 int retval;
1262 __ms_va_list valist;
1263 __ms_va_start(valist, format);
1264 retval = MSVCRT_vsnprintf_s_l(str, len, count, format, NULL, valist);
1265 __ms_va_end(valist);
1266 return retval;
1269 /*********************************************************************
1270 * _scprintf (MSVCRT.@)
1272 int WINAPIV MSVCRT__scprintf(const char *format, ...)
1274 int retval;
1275 __ms_va_list valist;
1276 __ms_va_start(valist, format);
1277 retval = MSVCRT__vscprintf(format, valist);
1278 __ms_va_end(valist);
1279 return retval;
1282 /*********************************************************************
1283 * _vsnwprintf (MSVCRT.@)
1285 int CDECL MSVCRT_vsnwprintf(MSVCRT_wchar_t *str, MSVCRT_size_t len,
1286 const MSVCRT_wchar_t *format, __ms_va_list valist)
1288 static const MSVCRT_wchar_t nullbyte = '\0';
1289 struct _str_ctx_w ctx = {len, str};
1290 int ret;
1292 ret = pf_printf_w(puts_clbk_str_w, &ctx, format, NULL, 0,
1293 arg_clbk_valist, NULL, &valist);
1294 puts_clbk_str_w(&ctx, 1, &nullbyte);
1295 return ret;
1298 /*********************************************************************
1299 * _vsnwprintf_l (MSVCRT.@)
1301 int CDECL MSVCRT_vsnwprintf_l(MSVCRT_wchar_t *str, MSVCRT_size_t len,
1302 const MSVCRT_wchar_t *format, MSVCRT__locale_t locale,
1303 __ms_va_list valist)
1305 static const MSVCRT_wchar_t nullbyte = '\0';
1306 struct _str_ctx_w ctx = {len, str};
1307 int ret;
1309 ret = pf_printf_w(puts_clbk_str_w, &ctx, format, locale, 0,
1310 arg_clbk_valist, NULL, &valist);
1311 puts_clbk_str_w(&ctx, 1, &nullbyte);
1312 return ret;
1315 /*********************************************************************
1316 * _vswprintf_c_l (MSVCRT.@)
1318 int CDECL MSVCRT_vswprintf_c_l(MSVCRT_wchar_t *str, MSVCRT_size_t len,
1319 const MSVCRT_wchar_t *format, MSVCRT__locale_t locale,
1320 __ms_va_list valist)
1322 return MSVCRT_vsnwprintf_s_l_opt(str, len, len, format, 0, locale, valist);
1325 /*********************************************************************
1326 * _vswprintf_c (MSVCRT.@)
1328 int CDECL MSVCRT_vswprintf_c(MSVCRT_wchar_t *str, MSVCRT_size_t len,
1329 const MSVCRT_wchar_t *format, __ms_va_list valist)
1331 return MSVCRT_vswprintf_c_l(str, len, format, NULL, valist);
1334 static int MSVCRT_vswprintf_p_l_opt(MSVCRT_wchar_t *buffer, MSVCRT_size_t length,
1335 const MSVCRT_wchar_t *format, DWORD options, MSVCRT__locale_t locale, __ms_va_list args)
1337 static const MSVCRT_wchar_t nullbyte = '\0';
1338 printf_arg args_ctx[MSVCRT__ARGMAX+1];
1339 struct _str_ctx_w puts_ctx = {length, buffer};
1340 int ret;
1342 memset(args_ctx, 0, sizeof(args_ctx));
1344 ret = create_positional_ctx_w(args_ctx, format, args);
1345 if(ret < 0) {
1346 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
1347 *MSVCRT__errno() = MSVCRT_EINVAL;
1348 return ret;
1349 } else if(ret == 0)
1350 ret = pf_printf_w(puts_clbk_str_w, &puts_ctx, format, locale, MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
1351 arg_clbk_valist, NULL, &args);
1352 else
1353 ret = pf_printf_w(puts_clbk_str_w, &puts_ctx, format, locale,
1354 MSVCRT_PRINTF_POSITIONAL_PARAMS | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
1355 arg_clbk_positional, args_ctx, NULL);
1357 puts_clbk_str_w(&puts_ctx, 1, &nullbyte);
1358 return ret;
1361 /*********************************************************************
1362 * _vswprintf_p_l (MSVCRT.@)
1364 int CDECL MSVCRT_vswprintf_p_l(MSVCRT_wchar_t *buffer, MSVCRT_size_t length,
1365 const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, __ms_va_list args)
1367 return MSVCRT_vswprintf_p_l_opt(buffer, length, format, 0, locale, args);
1370 #if _MSVCR_VER>=80
1371 /*********************************************************************
1372 * _vswprintf_p (MSVCR80.@)
1374 int CDECL MSVCRT__vswprintf_p(MSVCRT_wchar_t *buffer, MSVCRT_size_t length,
1375 const MSVCRT_wchar_t *format, __ms_va_list args)
1377 return MSVCRT_vswprintf_p_l_opt(buffer, length, format, 0, NULL, args);
1379 #endif
1381 #if _MSVCR_VER>=140
1382 /*********************************************************************
1383 * __stdio_common_vswprintf_p (UCRTBASE.@)
1385 int CDECL MSVCRT__stdio_common_vswprintf_p( unsigned __int64 options,
1386 MSVCRT_wchar_t *str, MSVCRT_size_t count, const MSVCRT_wchar_t *format,
1387 MSVCRT__locale_t locale, __ms_va_list valist )
1389 if (options & ~UCRTBASE_PRINTF_MASK)
1390 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
1391 return MSVCRT_vswprintf_p_l_opt(str, count, format, options & UCRTBASE_PRINTF_MASK, locale, valist);
1393 #endif
1395 /*********************************************************************
1396 * _vsnwprintf_s_l (MSVCRT.@)
1398 int CDECL MSVCRT_vsnwprintf_s_l( MSVCRT_wchar_t *str, MSVCRT_size_t sizeOfBuffer,
1399 MSVCRT_size_t count, const MSVCRT_wchar_t *format,
1400 MSVCRT__locale_t locale, __ms_va_list valist)
1402 return MSVCRT_vsnwprintf_s_l_opt(str, sizeOfBuffer, count, format, 0, locale, valist);
1405 /*********************************************************************
1406 * _vsnwprintf_s (MSVCRT.@)
1408 int CDECL MSVCRT_vsnwprintf_s(MSVCRT_wchar_t *str, MSVCRT_size_t sizeOfBuffer,
1409 MSVCRT_size_t count, const MSVCRT_wchar_t *format, __ms_va_list valist)
1411 return MSVCRT_vsnwprintf_s_l(str, sizeOfBuffer, count,
1412 format, NULL, valist);
1415 /*********************************************************************
1416 * _snwprintf (MSVCRT.@)
1418 int WINAPIV MSVCRT__snwprintf( MSVCRT_wchar_t *str, MSVCRT_size_t len, const MSVCRT_wchar_t *format, ...)
1420 int retval;
1421 __ms_va_list valist;
1422 __ms_va_start(valist, format);
1423 retval = MSVCRT_vsnwprintf(str, len, format, valist);
1424 __ms_va_end(valist);
1425 return retval;
1428 /*********************************************************************
1429 * _snwprintf_l (MSVCRT.@)
1431 int WINAPIV MSVCRT__snwprintf_l( MSVCRT_wchar_t *str, MSVCRT_size_t len, const MSVCRT_wchar_t *format,
1432 MSVCRT__locale_t locale, ...)
1434 int retval;
1435 __ms_va_list valist;
1436 __ms_va_start(valist, locale);
1437 retval = MSVCRT_vsnwprintf_l(str, len, format, locale, valist);
1438 __ms_va_end(valist);
1439 return retval;
1442 /*********************************************************************
1443 * _snwprintf_s (MSVCRT.@)
1445 int WINAPIV MSVCRT__snwprintf_s( MSVCRT_wchar_t *str, MSVCRT_size_t len, MSVCRT_size_t count,
1446 const MSVCRT_wchar_t *format, ...)
1448 int retval;
1449 __ms_va_list valist;
1450 __ms_va_start(valist, format);
1451 retval = MSVCRT_vsnwprintf_s_l(str, len, count, format, NULL, valist);
1452 __ms_va_end(valist);
1453 return retval;
1456 /*********************************************************************
1457 * _snwprintf_s_l (MSVCRT.@)
1459 int WINAPIV MSVCRT__snwprintf_s_l( MSVCRT_wchar_t *str, MSVCRT_size_t len, MSVCRT_size_t count,
1460 const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, ... )
1462 int retval;
1463 __ms_va_list valist;
1464 __ms_va_start(valist, locale);
1465 retval = MSVCRT_vsnwprintf_s_l(str, len, count, format, locale, valist);
1466 __ms_va_end(valist);
1467 return retval;
1470 #if _MSVCR_VER>=140
1472 static int puts_clbk_str_c99_w(void *ctx, int len, const MSVCRT_wchar_t *str)
1474 struct _str_ctx_w *out = ctx;
1476 if(!out->buf)
1477 return len;
1479 if(out->len < len) {
1480 memcpy(out->buf, str, out->len*sizeof(MSVCRT_wchar_t));
1481 out->buf += out->len;
1482 out->len = 0;
1483 return len;
1486 memcpy(out->buf, str, len*sizeof(MSVCRT_wchar_t));
1487 out->buf += len;
1488 out->len -= len;
1489 return len;
1492 /*********************************************************************
1493 * __stdio_common_vswprintf (UCRTBASE.@)
1495 int CDECL MSVCRT__stdio_common_vswprintf( unsigned __int64 options,
1496 MSVCRT_wchar_t *str, MSVCRT_size_t len, const MSVCRT_wchar_t *format,
1497 MSVCRT__locale_t locale, __ms_va_list valist )
1499 static const MSVCRT_wchar_t nullbyte = '\0';
1500 struct _str_ctx_w ctx = {len, str};
1501 int ret;
1503 if (options & ~UCRTBASE_PRINTF_MASK)
1504 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
1505 ret = pf_printf_w(puts_clbk_str_c99_w,
1506 &ctx, format, locale, options & UCRTBASE_PRINTF_MASK, arg_clbk_valist, NULL, &valist);
1507 puts_clbk_str_w(&ctx, 1, &nullbyte);
1509 if(!str)
1510 return ret;
1511 if(options & UCRTBASE_PRINTF_LEGACY_VSPRINTF_NULL_TERMINATION)
1512 return ret>len ? -1 : ret;
1513 if(ret>=len) {
1514 if(len) str[len-1] = 0;
1515 if(options & UCRTBASE_PRINTF_STANDARD_SNPRINTF_BEHAVIOUR)
1516 return ret;
1517 return len > 0 ? -2 : -1;
1519 return ret;
1522 #endif /* _MSVCR_VER>=140 */
1524 /*********************************************************************
1525 * sprintf (MSVCRT.@)
1527 int WINAPIV MSVCRT_sprintf( char *str, const char *format, ... )
1529 __ms_va_list ap;
1530 int r;
1532 __ms_va_start( ap, format );
1533 r = MSVCRT_vsnprintf( str, INT_MAX, format, ap );
1534 __ms_va_end( ap );
1535 return r;
1538 /*********************************************************************
1539 * sprintf_s (MSVCRT.@)
1541 int WINAPIV MSVCRT_sprintf_s( char *str, MSVCRT_size_t num, const char *format, ... )
1543 __ms_va_list ap;
1544 int r;
1546 __ms_va_start( ap, format );
1547 r = MSVCRT_vsnprintf( str, num, format, ap );
1548 __ms_va_end( ap );
1549 return r;
1552 /*********************************************************************
1553 * _scwprintf (MSVCRT.@)
1555 int WINAPIV MSVCRT__scwprintf( const MSVCRT_wchar_t *format, ... )
1557 __ms_va_list ap;
1558 int r;
1560 __ms_va_start( ap, format );
1561 r = MSVCRT_vsnwprintf( NULL, INT_MAX, format, ap );
1562 __ms_va_end( ap );
1563 return r;
1566 /*********************************************************************
1567 * swprintf (MSVCRT.@)
1569 int WINAPIV MSVCRT_swprintf( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *format, ... )
1571 __ms_va_list ap;
1572 int r;
1574 __ms_va_start( ap, format );
1575 r = MSVCRT_vsnwprintf( str, INT_MAX, format, ap );
1576 __ms_va_end( ap );
1577 return r;
1580 /*********************************************************************
1581 * swprintf_s (MSVCRT.@)
1583 int WINAPIV MSVCRT_swprintf_s(MSVCRT_wchar_t *str, MSVCRT_size_t numberOfElements,
1584 const MSVCRT_wchar_t *format, ... )
1586 __ms_va_list ap;
1587 int r;
1589 __ms_va_start(ap, format);
1590 r = MSVCRT_vsnwprintf_s(str, numberOfElements, INT_MAX, format, ap);
1591 __ms_va_end(ap);
1593 return r;
1596 /*********************************************************************
1597 * _swprintf_s_l (MSVCRT.@)
1599 int WINAPIV MSVCRT__swprintf_s_l(MSVCRT_wchar_t *str, MSVCRT_size_t numberOfElements,
1600 const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, ... )
1602 __ms_va_list ap;
1603 int r;
1605 __ms_va_start(ap, locale);
1606 r = MSVCRT_vsnwprintf_s_l(str, numberOfElements, INT_MAX, format, locale, ap);
1607 __ms_va_end(ap);
1609 return r;
1612 /*********************************************************************
1613 * _swprintf_c_l (MSVCRT.@)
1615 int WINAPIV MSVCRT_swprintf_c_l(MSVCRT_wchar_t *str, MSVCRT_size_t len,
1616 const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, ... )
1618 __ms_va_list ap;
1619 int r;
1621 __ms_va_start(ap, locale);
1622 r = MSVCRT_vswprintf_c_l(str, len, format, locale, ap);
1623 __ms_va_end(ap);
1625 return r;
1628 /*********************************************************************
1629 * _swprintf_c (MSVCRT.@)
1631 int WINAPIV MSVCRT_swprintf_c(MSVCRT_wchar_t *str, MSVCRT_size_t len,
1632 const MSVCRT_wchar_t *format, ... )
1634 __ms_va_list ap;
1635 int r;
1637 __ms_va_start(ap, format);
1638 r = MSVCRT_vswprintf_c(str, len, format, ap);
1639 __ms_va_end(ap);
1641 return r;
1644 /*********************************************************************
1645 * _vswprintf (MSVCRT.@)
1647 int CDECL MSVCRT_vswprintf( MSVCRT_wchar_t* str, const MSVCRT_wchar_t* format, __ms_va_list args )
1649 return MSVCRT_vsnwprintf( str, INT_MAX, format, args );
1652 /*********************************************************************
1653 * _vswprintf (MSVCRT.@)
1655 int CDECL MSVCRT_vswprintf_l( MSVCRT_wchar_t* str, const MSVCRT_wchar_t* format,
1656 MSVCRT__locale_t locale, __ms_va_list args )
1658 return MSVCRT_vsnwprintf_l( str, INT_MAX, format, locale, args );
1661 /*********************************************************************
1662 * _vscwprintf (MSVCRT.@)
1664 int CDECL MSVCRT__vscwprintf( const MSVCRT_wchar_t *format, __ms_va_list args )
1666 return MSVCRT_vsnwprintf( NULL, INT_MAX, format, args );
1669 /*********************************************************************
1670 * _vscwprintf_l (MSVCRT.@)
1672 int CDECL MSVCRT__vscwprintf_l( const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, __ms_va_list args )
1674 return MSVCRT_vsnwprintf_l( NULL, INT_MAX, format, locale, args );
1677 /*********************************************************************
1678 * _vscwprintf_p_l (MSVCRT.@)
1680 int CDECL MSVCRT__vscwprintf_p_l( const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, __ms_va_list args )
1682 return MSVCRT_vswprintf_p_l_opt( NULL, INT_MAX, format, 0, locale, args );
1685 #if _MSVCR_VER>=80
1686 /*********************************************************************
1687 * _vscwprintf_p (MSVCR80.@)
1689 int CDECL MSVCRT__vscwprintf_p(const MSVCRT_wchar_t *format, __ms_va_list args)
1691 return MSVCRT_vswprintf_p_l_opt(NULL, INT_MAX, format, 0, NULL, args);
1693 #endif
1695 /*********************************************************************
1696 * vswprintf_s (MSVCRT.@)
1698 int CDECL MSVCRT_vswprintf_s(MSVCRT_wchar_t* str, MSVCRT_size_t numberOfElements,
1699 const MSVCRT_wchar_t* format, __ms_va_list args)
1701 return MSVCRT_vsnwprintf_s(str, numberOfElements, INT_MAX, format, args );
1704 /*********************************************************************
1705 * _vswprintf_s_l (MSVCRT.@)
1707 int CDECL MSVCRT_vswprintf_s_l(MSVCRT_wchar_t* str, MSVCRT_size_t numberOfElements,
1708 const MSVCRT_wchar_t* format, MSVCRT__locale_t locale, __ms_va_list args)
1710 return MSVCRT_vsnwprintf_s_l(str, numberOfElements, INT_MAX,
1711 format, locale, args );
1714 static int MSVCRT_vsprintf_p_l_opt(char *buffer, MSVCRT_size_t length, const char *format,
1715 DWORD options, MSVCRT__locale_t locale, __ms_va_list args)
1717 static const char nullbyte = '\0';
1718 printf_arg args_ctx[MSVCRT__ARGMAX+1];
1719 struct _str_ctx_a puts_ctx = {length, buffer};
1720 int ret;
1722 memset(args_ctx, 0, sizeof(args_ctx));
1724 ret = create_positional_ctx_a(args_ctx, format, args);
1725 if(ret < 0) {
1726 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
1727 *MSVCRT__errno() = MSVCRT_EINVAL;
1728 return ret;
1729 } else if(ret == 0)
1730 ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale,
1731 MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options, arg_clbk_valist, NULL, &args);
1732 else
1733 ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale,
1734 MSVCRT_PRINTF_POSITIONAL_PARAMS | MSVCRT_PRINTF_INVOKE_INVALID_PARAM_HANDLER | options,
1735 arg_clbk_positional, args_ctx, NULL);
1737 puts_clbk_str_a(&puts_ctx, 1, &nullbyte);
1738 return ret;
1741 /*********************************************************************
1742 * _vsprintf_p_l (MSVCRT.@)
1744 int CDECL MSVCRT_vsprintf_p_l(char *buffer, MSVCRT_size_t length, const char *format,
1745 MSVCRT__locale_t locale, __ms_va_list args)
1747 return MSVCRT_vsprintf_p_l_opt(buffer, length, format, 0, locale, args);
1750 /*********************************************************************
1751 * _vsprintf_p (MSVCRT.@)
1753 int CDECL MSVCRT_vsprintf_p(char *buffer, MSVCRT_size_t length,
1754 const char *format, __ms_va_list args)
1756 return MSVCRT_vsprintf_p_l(buffer, length, format, NULL, args);
1759 #if _MSVCR_VER>=140
1760 /*********************************************************************
1761 * __stdio_common_vsprintf_p (UCRTBASE.@)
1763 int CDECL MSVCRT__stdio_common_vsprintf_p(unsigned __int64 options, char *buffer, MSVCRT_size_t length,
1764 const char *format, MSVCRT__locale_t locale, __ms_va_list args)
1766 if (options & ~UCRTBASE_PRINTF_MASK)
1767 FIXME("options %s not handled\n", wine_dbgstr_longlong(options));
1768 return MSVCRT_vsprintf_p_l_opt(buffer, length, format, options & UCRTBASE_PRINTF_MASK, locale, args);
1770 #endif
1772 /*********************************************************************
1773 * _sprintf_p_l (MSVCRT.@)
1775 int WINAPIV MSVCRT_sprintf_p_l(char *buffer, MSVCRT_size_t length,
1776 const char *format, MSVCRT__locale_t locale, ...)
1778 __ms_va_list valist;
1779 int r;
1781 __ms_va_start(valist, locale);
1782 r = MSVCRT_vsprintf_p_l(buffer, length, format, locale, valist);
1783 __ms_va_end(valist);
1785 return r;
1788 /*********************************************************************
1789 * __swprintf_l (MSVCRT.@)
1791 int WINAPIV MSVCRT___swprintf_l( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *format,
1792 MSVCRT__locale_t locale, ...)
1794 int retval;
1795 __ms_va_list valist;
1796 __ms_va_start(valist, locale);
1797 retval = MSVCRT_vswprintf_l(str, format, locale, valist);
1798 __ms_va_end(valist);
1799 return retval;
1802 #if _MSVCR_VER>=80
1803 /*********************************************************************
1804 * _sprintf_p (MSVCR80.@)
1806 int WINAPIV MSVCRT__sprintf_p(char *buffer, MSVCRT_size_t length, const char *format, ...)
1808 __ms_va_list valist;
1809 int r;
1811 __ms_va_start(valist, format);
1812 r = MSVCRT_vsprintf_p_l(buffer, length, format, NULL, valist);
1813 __ms_va_end(valist);
1815 return r;
1817 #endif
1819 /*********************************************************************
1820 * _swprintf_p_l (MSVCRT.@)
1822 int WINAPIV MSVCRT_swprintf_p_l(MSVCRT_wchar_t *buffer, MSVCRT_size_t length,
1823 const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, ...)
1825 __ms_va_list valist;
1826 int r;
1828 __ms_va_start(valist, locale);
1829 r = MSVCRT_vswprintf_p_l_opt(buffer, length, format, 0, locale, valist);
1830 __ms_va_end(valist);
1832 return r;
1835 /*********************************************************************
1836 * wcscmp (MSVCRT.@)
1838 int CDECL MSVCRT_wcscmp(const MSVCRT_wchar_t *str1, const MSVCRT_wchar_t *str2)
1840 while (*str1 && (*str1 == *str2))
1842 str1++;
1843 str2++;
1846 if (*str1 < *str2)
1847 return -1;
1848 if (*str1 > *str2)
1849 return 1;
1850 return 0;
1853 /*********************************************************************
1854 * _wcscoll_l (MSVCRT.@)
1856 int CDECL MSVCRT__wcscoll_l(const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2, MSVCRT__locale_t locale)
1858 MSVCRT_pthreadlocinfo locinfo;
1860 if(!locale)
1861 locinfo = get_locinfo();
1862 else
1863 locinfo = locale->locinfo;
1865 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE])
1866 return MSVCRT_wcscmp(str1, str2);
1867 return CompareStringW(locinfo->lc_handle[MSVCRT_LC_COLLATE], 0, str1, -1, str2, -1)-CSTR_EQUAL;
1870 /*********************************************************************
1871 * wcscoll (MSVCRT.@)
1873 int CDECL MSVCRT_wcscoll( const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2 )
1875 return MSVCRT__wcscoll_l(str1, str2, NULL);
1878 /*********************************************************************
1879 * wcspbrk (MSVCRT.@)
1881 MSVCRT_wchar_t* CDECL MSVCRT_wcspbrk( const MSVCRT_wchar_t* str, const MSVCRT_wchar_t* accept )
1883 const MSVCRT_wchar_t* p;
1885 while (*str)
1887 for (p = accept; *p; p++) if (*p == *str) return (MSVCRT_wchar_t*)str;
1888 str++;
1890 return NULL;
1893 /*********************************************************************
1894 * wcstok_s (MSVCRT.@)
1896 MSVCRT_wchar_t * CDECL MSVCRT_wcstok_s( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *delim,
1897 MSVCRT_wchar_t **next_token )
1899 MSVCRT_wchar_t *ret;
1901 if (!MSVCRT_CHECK_PMT(delim != NULL)) return NULL;
1902 if (!MSVCRT_CHECK_PMT(next_token != NULL)) return NULL;
1903 if (!MSVCRT_CHECK_PMT(str != NULL || *next_token != NULL)) return NULL;
1905 if (!str) str = *next_token;
1907 while (*str && MSVCRT_wcschr( delim, *str )) str++;
1908 if (!*str) return NULL;
1909 ret = str++;
1910 while (*str && !MSVCRT_wcschr( delim, *str )) str++;
1911 if (*str) *str++ = 0;
1912 *next_token = str;
1913 return ret;
1916 /*********************************************************************
1917 * wcstok (MSVCRT.@)
1919 #if _MSVCR_VER>=140
1920 MSVCRT_wchar_t * CDECL MSVCRT_wcstok( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *delim, MSVCRT_wchar_t **ctx )
1922 if (!ctx)
1923 ctx = &msvcrt_get_thread_data()->wcstok_next;
1924 return MSVCRT_wcstok_s(str, delim, ctx);
1926 #else
1927 MSVCRT_wchar_t * CDECL MSVCRT_wcstok( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *delim )
1929 return MSVCRT_wcstok_s(str, delim, &msvcrt_get_thread_data()->wcstok_next);
1931 #endif
1933 /*********************************************************************
1934 * _wctomb_s_l (MSVCRT.@)
1936 int CDECL MSVCRT__wctomb_s_l(int *len, char *mbchar, MSVCRT_size_t size,
1937 MSVCRT_wchar_t wch, MSVCRT__locale_t locale)
1939 MSVCRT_pthreadlocinfo locinfo;
1940 BOOL error = FALSE;
1941 BOOL *perror;
1942 int mblen;
1944 if(!mbchar && size>0) {
1945 if(len)
1946 *len = 0;
1947 return 0;
1950 if(len)
1951 *len = -1;
1953 if(!MSVCRT_CHECK_PMT(size <= INT_MAX))
1954 return MSVCRT_EINVAL;
1956 if(!locale)
1957 locinfo = get_locinfo();
1958 else
1959 locinfo = locale->locinfo;
1961 if(!locinfo->lc_codepage) {
1962 if(wch > 0xff) {
1963 if(mbchar && size>0)
1964 memset(mbchar, 0, size);
1965 *MSVCRT__errno() = MSVCRT_EILSEQ;
1966 return MSVCRT_EILSEQ;
1969 if(!MSVCRT_CHECK_PMT_ERR(size >= 1, MSVCRT_ERANGE))
1970 return MSVCRT_ERANGE;
1972 *mbchar = wch;
1973 if(len)
1974 *len = 1;
1975 return 0;
1978 perror = (locinfo->lc_codepage != CP_UTF8 ? &error : NULL);
1979 mblen = WideCharToMultiByte(locinfo->lc_codepage, 0, &wch, 1, mbchar, size, NULL, perror);
1980 if(!mblen || error) {
1981 if(!mblen && GetLastError()==ERROR_INSUFFICIENT_BUFFER) {
1982 if(mbchar && size>0)
1983 memset(mbchar, 0, size);
1985 MSVCRT_INVALID_PMT("insufficient buffer size", MSVCRT_ERANGE);
1986 return MSVCRT_ERANGE;
1989 *MSVCRT__errno() = MSVCRT_EILSEQ;
1990 return MSVCRT_EILSEQ;
1993 if(len)
1994 *len = mblen;
1995 return 0;
1998 /*********************************************************************
1999 * wctomb_s (MSVCRT.@)
2001 int CDECL MSVCRT_wctomb_s(int *len, char *mbchar, MSVCRT_size_t size, MSVCRT_wchar_t wch)
2003 return MSVCRT__wctomb_s_l(len, mbchar, size, wch, NULL);
2006 /*********************************************************************
2007 * _wctomb_l (MSVCRT.@)
2009 int CDECL MSVCRT__wctomb_l(char *dst, MSVCRT_wchar_t ch, MSVCRT__locale_t locale)
2011 int len;
2013 MSVCRT__wctomb_s_l(&len, dst, dst ? MSVCRT_MB_LEN_MAX : 0, ch, locale);
2014 return len;
2017 /*********************************************************************
2018 * wctomb (MSVCRT.@)
2020 INT CDECL MSVCRT_wctomb( char *dst, MSVCRT_wchar_t ch )
2022 return MSVCRT__wctomb_l(dst, ch, NULL);
2025 /*********************************************************************
2026 * wctob (MSVCRT.@)
2028 INT CDECL MSVCRT_wctob( MSVCRT_wint_t wchar )
2030 char out;
2031 BOOL error = FALSE;
2032 BOOL *perror;
2033 UINT codepage = get_locinfo()->lc_codepage;
2035 perror = (codepage != CP_UTF8 ? &error : NULL);
2037 if(!codepage) {
2038 if (wchar < 0xff)
2039 return (signed char)wchar;
2040 else
2041 return MSVCRT_EOF;
2042 } else if(WideCharToMultiByte( codepage, 0, &wchar, 1, &out, 1, NULL, perror ) && !error)
2043 return (INT)out;
2044 return MSVCRT_EOF;
2047 /*********************************************************************
2048 * wcrtomb_s (MSVCRT.@)
2050 INT CDECL MSVCRT_wcrtomb_s(MSVCRT_size_t *len, char *mbchar,
2051 MSVCRT_size_t size, MSVCRT_wchar_t wch, MSVCRT_mbstate_t *s)
2053 int ilen, ret;
2055 if (s) *s = 0;
2056 ret = MSVCRT_wctomb_s(&ilen, mbchar, size, wch);
2057 if (len) *len = ilen;
2058 return ret;
2061 /*********************************************************************
2062 * wcrtomb (MSVCRT.@)
2064 MSVCRT_size_t CDECL MSVCRT_wcrtomb( char *dst, MSVCRT_wchar_t ch, MSVCRT_mbstate_t *s)
2066 if(s)
2067 *s = 0;
2068 return MSVCRT_wctomb(dst, ch);
2071 /*********************************************************************
2072 * _iswctype_l (MSVCRT.@)
2074 INT CDECL MSVCRT__iswctype_l( MSVCRT_wchar_t wc, MSVCRT_wctype_t type, MSVCRT__locale_t locale )
2076 WORD ct;
2078 if (wc == MSVCRT_WEOF) return 0;
2079 if (wc < 256) return MSVCRT__pwctype[wc] & type;
2081 if (!GetStringTypeW(CT_CTYPE1, &wc, 1, &ct))
2083 ERR("GetStringTypeW failed for %x\n", wc);
2084 return 0;
2086 return ct & type;
2089 /*********************************************************************
2090 * iswctype (MSVCRT.@)
2092 INT CDECL MSVCRT_iswctype( MSVCRT_wchar_t wc, MSVCRT_wctype_t type )
2094 return MSVCRT__iswctype_l( wc, type, NULL );
2097 /*********************************************************************
2098 * _iswalnum_l (MSVCRT.@)
2100 int CDECL MSVCRT__iswalnum_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
2102 return MSVCRT__iswctype_l( wc, MSVCRT__ALPHA | MSVCRT__DIGIT, locale );
2105 /*********************************************************************
2106 * iswalnum (MSVCRT.@)
2108 INT CDECL MSVCRT_iswalnum( MSVCRT_wchar_t wc )
2110 return MSVCRT__iswalnum_l( wc, NULL );
2113 /*********************************************************************
2114 * iswalpha_l (MSVCRT.@)
2116 INT CDECL MSVCRT__iswalpha_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
2118 return MSVCRT__iswctype_l( wc, MSVCRT__ALPHA, locale );
2121 /*********************************************************************
2122 * iswalpha (MSVCRT.@)
2124 INT CDECL MSVCRT_iswalpha( MSVCRT_wchar_t wc )
2126 return MSVCRT__iswalpha_l( wc, NULL );
2129 /*********************************************************************
2130 * _iswcntrl_l (MSVCRT.@)
2132 int CDECL MSVCRT__iswcntrl_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
2134 return MSVCRT__iswctype_l( wc, MSVCRT__CONTROL, locale );
2137 /*********************************************************************
2138 * iswcntrl (MSVCRT.@)
2140 INT CDECL MSVCRT_iswcntrl( MSVCRT_wchar_t wc )
2142 return MSVCRT__iswcntrl_l( wc, NULL );
2145 /*********************************************************************
2146 * _iswdigit_l (MSVCRT.@)
2148 INT CDECL MSVCRT__iswdigit_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
2150 return MSVCRT__iswctype_l( wc, MSVCRT__DIGIT, locale );
2153 /*********************************************************************
2154 * iswdigit (MSVCRT.@)
2156 INT CDECL MSVCRT_iswdigit( MSVCRT_wchar_t wc )
2158 return MSVCRT__iswdigit_l( wc, NULL );
2161 /*********************************************************************
2162 * _iswgraph_l (MSVCRT.@)
2164 int CDECL MSVCRT__iswgraph_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
2166 return MSVCRT__iswctype_l( wc, MSVCRT__ALPHA | MSVCRT__DIGIT | MSVCRT__PUNCT, locale );
2169 /*********************************************************************
2170 * iswgraph (MSVCRT.@)
2172 INT CDECL MSVCRT_iswgraph( MSVCRT_wchar_t wc )
2174 return MSVCRT__iswgraph_l( wc, NULL );
2177 /*********************************************************************
2178 * _iswlower_l (MSVCRT.@)
2180 int CDECL MSVCRT__iswlower_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
2182 return MSVCRT__iswctype_l( wc, MSVCRT__LOWER, locale );
2185 /*********************************************************************
2186 * iswlower (MSVCRT.@)
2188 INT CDECL MSVCRT_iswlower( MSVCRT_wchar_t wc )
2190 return MSVCRT__iswlower_l( wc, NULL );
2193 /*********************************************************************
2194 * _iswprint_l (MSVCRT.@)
2196 int CDECL MSVCRT__iswprint_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
2198 return MSVCRT__iswctype_l( wc, MSVCRT__ALPHA | MSVCRT__BLANK |
2199 MSVCRT__DIGIT | MSVCRT__PUNCT, locale );
2202 /*********************************************************************
2203 * iswprint (MSVCRT.@)
2205 INT CDECL MSVCRT_iswprint( MSVCRT_wchar_t wc )
2207 return MSVCRT__iswprint_l( wc, NULL );
2210 /*********************************************************************
2211 * _iswpunct_l (MSVCRT.@)
2213 INT CDECL MSVCRT__iswpunct_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
2215 return MSVCRT__iswctype_l( wc, MSVCRT__PUNCT, locale );
2218 /*********************************************************************
2219 * iswpunct (MSVCRT.@)
2221 INT CDECL MSVCRT_iswpunct( MSVCRT_wchar_t wc )
2223 return MSVCRT__iswpunct_l( wc, NULL );
2226 /*********************************************************************
2227 * _iswspace_l (MSVCRT.@)
2229 INT CDECL MSVCRT__iswspace_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
2231 return MSVCRT__iswctype_l( wc, MSVCRT__SPACE, locale );
2234 /*********************************************************************
2235 * iswspace (MSVCRT.@)
2237 INT CDECL MSVCRT_iswspace( MSVCRT_wchar_t wc )
2239 return MSVCRT__iswspace_l( wc, NULL );
2242 /*********************************************************************
2243 * _iswupper_l (MSVCRT.@)
2245 int CDECL MSVCRT__iswupper_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
2247 return MSVCRT__iswctype_l( wc, MSVCRT__UPPER, locale );
2250 /*********************************************************************
2251 * iswupper (MSVCRT.@)
2253 INT CDECL MSVCRT_iswupper( MSVCRT_wchar_t wc )
2255 return MSVCRT__iswupper_l( wc, NULL );
2258 /*********************************************************************
2259 * _iswxdigit_l (MSVCRT.@)
2261 int CDECL MSVCRT__iswxdigit_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
2263 return MSVCRT__iswctype_l( wc, MSVCRT__HEX, locale );
2266 /*********************************************************************
2267 * iswxdigit (MSVCRT.@)
2269 INT CDECL MSVCRT_iswxdigit( MSVCRT_wchar_t wc )
2271 return MSVCRT__iswxdigit_l( wc, NULL );
2274 /*********************************************************************
2275 * _iswblank_l (MSVCRT.@)
2277 INT CDECL MSVCRT__iswblank_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
2279 return wc == '\t' || MSVCRT__iswctype_l( wc, MSVCRT__BLANK, locale );
2282 /*********************************************************************
2283 * iswblank (MSVCRT.@)
2285 INT CDECL MSVCRT_iswblank( MSVCRT_wchar_t wc )
2287 return wc == '\t' || MSVCRT__iswctype_l( wc, MSVCRT__BLANK, NULL );
2290 /*********************************************************************
2291 * wcscpy_s (MSVCRT.@)
2293 INT CDECL MSVCRT_wcscpy_s( MSVCRT_wchar_t* wcDest, MSVCRT_size_t numElement, const MSVCRT_wchar_t *wcSrc)
2295 MSVCRT_size_t size = 0;
2297 if(!MSVCRT_CHECK_PMT(wcDest)) return MSVCRT_EINVAL;
2298 if(!MSVCRT_CHECK_PMT(numElement)) return MSVCRT_EINVAL;
2300 if(!MSVCRT_CHECK_PMT(wcSrc))
2302 wcDest[0] = 0;
2303 return MSVCRT_EINVAL;
2306 size = MSVCRT_wcslen(wcSrc) + 1;
2308 if(!MSVCRT_CHECK_PMT_ERR(size <= numElement, MSVCRT_ERANGE))
2310 wcDest[0] = 0;
2311 return MSVCRT_ERANGE;
2314 memmove( wcDest, wcSrc, size*sizeof(WCHAR) );
2316 return 0;
2319 /***********************************************************************
2320 * wcscpy (MSVCRT.@)
2322 MSVCRT_wchar_t* __cdecl MSVCRT_wcscpy( MSVCRT_wchar_t *dst, const MSVCRT_wchar_t *src )
2324 WCHAR *p = dst;
2325 while ((*p++ = *src++));
2326 return dst;
2329 /******************************************************************
2330 * wcsncpy (MSVCRT.@)
2332 MSVCRT_wchar_t* __cdecl MSVCRT_wcsncpy( MSVCRT_wchar_t* s1,
2333 const MSVCRT_wchar_t *s2, MSVCRT_size_t n )
2335 MSVCRT_size_t i;
2337 for(i=0; i<n; i++)
2338 if(!(s1[i] = s2[i])) break;
2339 for(; i<n; i++)
2340 s1[i] = 0;
2341 return s1;
2344 /******************************************************************
2345 * wcsncpy_s (MSVCRT.@)
2347 INT CDECL MSVCRT_wcsncpy_s( MSVCRT_wchar_t* wcDest, MSVCRT_size_t numElement, const MSVCRT_wchar_t *wcSrc,
2348 MSVCRT_size_t count )
2350 WCHAR *p = wcDest;
2351 BOOL truncate = (count == MSVCRT__TRUNCATE);
2353 if(!wcDest && !numElement && !count)
2354 return 0;
2356 if (!wcDest || !numElement)
2357 return MSVCRT_EINVAL;
2359 if (!wcSrc)
2361 *wcDest = 0;
2362 return count ? MSVCRT_EINVAL : 0;
2365 while (numElement && count && *wcSrc)
2367 *p++ = *wcSrc++;
2368 numElement--;
2369 count--;
2371 if (!numElement && truncate)
2373 *(p-1) = 0;
2374 return MSVCRT_STRUNCATE;
2376 else if (!numElement)
2378 *wcDest = 0;
2379 return MSVCRT_ERANGE;
2382 *p = 0;
2383 return 0;
2386 /******************************************************************
2387 * wcscat_s (MSVCRT.@)
2390 INT CDECL MSVCRT_wcscat_s(MSVCRT_wchar_t* dst, MSVCRT_size_t elem, const MSVCRT_wchar_t* src)
2392 MSVCRT_wchar_t* ptr = dst;
2394 if (!dst || elem == 0) return MSVCRT_EINVAL;
2395 if (!src)
2397 dst[0] = '\0';
2398 return MSVCRT_EINVAL;
2401 /* seek to end of dst string (or elem if no end of string is found */
2402 while (ptr < dst + elem && *ptr != '\0') ptr++;
2403 while (ptr < dst + elem)
2405 if ((*ptr++ = *src++) == '\0') return 0;
2407 /* not enough space */
2408 dst[0] = '\0';
2409 return MSVCRT_ERANGE;
2412 /***********************************************************************
2413 * wcscat (MSVCRT.@)
2415 MSVCRT_wchar_t* __cdecl MSVCRT_wcscat( MSVCRT_wchar_t *dst, const MSVCRT_wchar_t *src )
2417 MSVCRT_wcscpy( dst + MSVCRT_wcslen(dst), src );
2418 return dst;
2421 /*********************************************************************
2422 * wcsncat_s (MSVCRT.@)
2425 INT CDECL MSVCRT_wcsncat_s(MSVCRT_wchar_t *dst, MSVCRT_size_t elem,
2426 const MSVCRT_wchar_t *src, MSVCRT_size_t count)
2428 MSVCRT_size_t srclen;
2429 MSVCRT_wchar_t dststart;
2430 INT ret = 0;
2432 if (!MSVCRT_CHECK_PMT(dst != NULL)) return MSVCRT_EINVAL;
2433 if (!MSVCRT_CHECK_PMT(elem > 0)) return MSVCRT_EINVAL;
2434 if (!MSVCRT_CHECK_PMT(src != NULL || count == 0)) return MSVCRT_EINVAL;
2436 if (count == 0)
2437 return 0;
2439 for (dststart = 0; dststart < elem; dststart++)
2441 if (dst[dststart] == '\0')
2442 break;
2444 if (dststart == elem)
2446 MSVCRT_INVALID_PMT("dst[elem] is not NULL terminated\n", MSVCRT_EINVAL);
2447 return MSVCRT_EINVAL;
2450 if (count == MSVCRT__TRUNCATE)
2452 srclen = MSVCRT_wcslen(src);
2453 if (srclen >= (elem - dststart))
2455 srclen = elem - dststart - 1;
2456 ret = MSVCRT_STRUNCATE;
2459 else
2460 srclen = min(MSVCRT_wcslen(src), count);
2461 if (srclen < (elem - dststart))
2463 memcpy(&dst[dststart], src, srclen*sizeof(MSVCRT_wchar_t));
2464 dst[dststart+srclen] = '\0';
2465 return ret;
2467 MSVCRT_INVALID_PMT("dst[elem] is too small", MSVCRT_ERANGE);
2468 dst[0] = '\0';
2469 return MSVCRT_ERANGE;
2472 /*********************************************************************
2473 * wctoint (INTERNAL)
2475 static int wctoint(WCHAR c, int base)
2477 int v = -1;
2478 if ('0' <= c && c <= '9')
2479 v = c - '0';
2480 else if ('A' <= c && c <= 'Z')
2481 v = c - 'A' + 10;
2482 else if ('a' <= c && c <= 'z')
2483 v = c - 'a' + 10;
2484 else {
2485 /* NOTE: wine_fold_string(MAP_FOLDDIGITS) supports too many things. */
2486 /* Unicode points that contain digits 0-9; keep this sorted! */
2487 static const WCHAR zeros[] = {
2488 0x660, 0x6f0, 0x966, 0x9e6, 0xa66, 0xae6, 0xb66, 0xc66, 0xce6,
2489 0xd66, 0xe50, 0xed0, 0xf20, 0x1040, 0x17e0, 0x1810, 0xff10
2491 int i;
2492 for (i = 0; i < ARRAY_SIZE(zeros) && c >= zeros[i]; ++i) {
2493 if (zeros[i] <= c && c <= zeros[i] + 9) {
2494 v = c - zeros[i];
2495 break;
2499 return v < base ? v : -1;
2502 /*********************************************************************
2503 * _wcstoi64_l (MSVCRT.@)
2505 * FIXME: locale parameter is ignored
2507 __int64 CDECL MSVCRT__wcstoi64_l(const MSVCRT_wchar_t *nptr,
2508 MSVCRT_wchar_t **endptr, int base, MSVCRT__locale_t locale)
2510 BOOL negative = FALSE, empty = TRUE;
2511 __int64 ret = 0;
2513 TRACE("(%s %p %d %p)\n", debugstr_w(nptr), endptr, base, locale);
2515 if (!MSVCRT_CHECK_PMT(nptr != NULL)) return 0;
2516 if (!MSVCRT_CHECK_PMT(base == 0 || base >= 2)) return 0;
2517 if (!MSVCRT_CHECK_PMT(base <= 36)) return 0;
2519 if(endptr)
2520 *endptr = (MSVCRT_wchar_t*)nptr;
2522 while(MSVCRT__iswspace_l(*nptr, locale)) nptr++;
2524 if(*nptr == '-') {
2525 negative = TRUE;
2526 nptr++;
2527 } else if(*nptr == '+')
2528 nptr++;
2530 if((base==0 || base==16) && wctoint(*nptr, 1)==0 && (nptr[1]=='x' || nptr[1]=='X')) {
2531 base = 16;
2532 nptr += 2;
2535 if(base == 0) {
2536 if(wctoint(*nptr, 1)==0)
2537 base = 8;
2538 else
2539 base = 10;
2542 while(*nptr) {
2543 int v = wctoint(*nptr, base);
2544 if(v<0)
2545 break;
2547 if(negative)
2548 v = -v;
2550 nptr++;
2551 empty = FALSE;
2553 if(!negative && (ret>MSVCRT_I64_MAX/base || ret*base>MSVCRT_I64_MAX-v)) {
2554 ret = MSVCRT_I64_MAX;
2555 *MSVCRT__errno() = MSVCRT_ERANGE;
2556 } else if(negative && (ret<MSVCRT_I64_MIN/base || ret*base<MSVCRT_I64_MIN-v)) {
2557 ret = MSVCRT_I64_MIN;
2558 *MSVCRT__errno() = MSVCRT_ERANGE;
2559 } else
2560 ret = ret*base + v;
2563 if(endptr && !empty)
2564 *endptr = (MSVCRT_wchar_t*)nptr;
2566 return ret;
2569 /*********************************************************************
2570 * _wcstoi64 (MSVCRT.@)
2572 __int64 CDECL MSVCRT__wcstoi64(const MSVCRT_wchar_t *nptr,
2573 MSVCRT_wchar_t **endptr, int base)
2575 return MSVCRT__wcstoi64_l(nptr, endptr, base, NULL);
2578 /*********************************************************************
2579 * _wcstol_l (MSVCRT.@)
2581 MSVCRT_long CDECL MSVCRT__wcstol_l(const MSVCRT_wchar_t *s,
2582 MSVCRT_wchar_t **end, int base, MSVCRT__locale_t locale)
2584 __int64 ret = MSVCRT__wcstoi64_l(s, end, base, locale);
2586 if(ret > MSVCRT_LONG_MAX) {
2587 ret = MSVCRT_LONG_MAX;
2588 *MSVCRT__errno() = MSVCRT_ERANGE;
2589 }else if(ret < MSVCRT_LONG_MIN) {
2590 ret = MSVCRT_LONG_MIN;
2591 *MSVCRT__errno() = MSVCRT_ERANGE;
2593 return ret;
2596 /*********************************************************************
2597 * wcstol (MSVCRT.@)
2599 MSVCRT_long CDECL MSVCRT_wcstol(const MSVCRT_wchar_t *s,
2600 MSVCRT_wchar_t **end, int base)
2602 return MSVCRT__wcstol_l(s, end, base, NULL);
2605 /*********************************************************************
2606 * _wtoi_l (MSVCRT.@)
2608 int __cdecl MSVCRT__wtoi_l(const MSVCRT_wchar_t *str, MSVCRT__locale_t locale)
2610 __int64 ret = MSVCRT__wcstoi64_l(str, NULL, 10, locale);
2612 if(ret > INT_MAX) {
2613 ret = INT_MAX;
2614 *MSVCRT__errno() = MSVCRT_ERANGE;
2615 } else if(ret < INT_MIN) {
2616 ret = INT_MIN;
2617 *MSVCRT__errno() = MSVCRT_ERANGE;
2619 return ret;
2622 /*********************************************************************
2623 * _wtoi (MSVCRT.@)
2625 int __cdecl MSVCRT__wtoi(const MSVCRT_wchar_t *str)
2627 return MSVCRT__wtoi_l(str, NULL);
2630 /*********************************************************************
2631 * _wtol_l (MSVCRT.@)
2633 MSVCRT_long __cdecl MSVCRT__wtol_l(const MSVCRT_wchar_t *str, MSVCRT__locale_t locale)
2635 __int64 ret = MSVCRT__wcstoi64_l(str, NULL, 10, locale);
2637 if(ret > MSVCRT_LONG_MAX) {
2638 ret = MSVCRT_LONG_MAX;
2639 *MSVCRT__errno() = MSVCRT_ERANGE;
2640 } else if(ret < MSVCRT_LONG_MIN) {
2641 ret = MSVCRT_LONG_MIN;
2642 *MSVCRT__errno() = MSVCRT_ERANGE;
2644 return ret;
2647 /*********************************************************************
2648 * _wtol (MSVCRT.@)
2650 MSVCRT_long __cdecl MSVCRT__wtol(const MSVCRT_wchar_t *str)
2652 return MSVCRT__wtol_l(str, NULL);
2655 #if _MSVCR_VER>=120
2657 /*********************************************************************
2658 * _wtoll_l (MSVCR120.@)
2660 MSVCRT_longlong __cdecl MSVCRT__wtoll_l(const MSVCRT_wchar_t *str, MSVCRT__locale_t locale)
2662 return MSVCRT__wcstoi64_l(str, NULL, 10, locale);
2665 /*********************************************************************
2666 * _wtoll (MSVCR120.@)
2668 MSVCRT_longlong __cdecl MSVCRT__wtoll(const MSVCRT_wchar_t *str)
2670 return MSVCRT__wtoll_l(str, NULL);
2673 #endif /* _MSVCR_VER>=120 */
2675 /*********************************************************************
2676 * _wcstoui64_l (MSVCRT.@)
2678 * FIXME: locale parameter is ignored
2680 unsigned __int64 CDECL MSVCRT__wcstoui64_l(const MSVCRT_wchar_t *nptr,
2681 MSVCRT_wchar_t **endptr, int base, MSVCRT__locale_t locale)
2683 BOOL negative = FALSE, empty = TRUE;
2684 unsigned __int64 ret = 0;
2686 TRACE("(%s %p %d %p)\n", debugstr_w(nptr), endptr, base, locale);
2688 if (!MSVCRT_CHECK_PMT(nptr != NULL)) return 0;
2689 if (!MSVCRT_CHECK_PMT(base == 0 || base >= 2)) return 0;
2690 if (!MSVCRT_CHECK_PMT(base <= 36)) return 0;
2692 if(endptr)
2693 *endptr = (MSVCRT_wchar_t*)nptr;
2695 while(MSVCRT__iswspace_l(*nptr, locale)) nptr++;
2697 if(*nptr == '-') {
2698 negative = TRUE;
2699 nptr++;
2700 } else if(*nptr == '+')
2701 nptr++;
2703 if((base==0 || base==16) && wctoint(*nptr, 1)==0 && (nptr[1]=='x' || nptr[1]=='X')) {
2704 base = 16;
2705 nptr += 2;
2708 if(base == 0) {
2709 if(wctoint(*nptr, 1)==0)
2710 base = 8;
2711 else
2712 base = 10;
2715 while(*nptr) {
2716 int v = wctoint(*nptr, base);
2717 if(v<0)
2718 break;
2720 nptr++;
2721 empty = FALSE;
2723 if(ret>MSVCRT_UI64_MAX/base || ret*base>MSVCRT_UI64_MAX-v) {
2724 ret = MSVCRT_UI64_MAX;
2725 *MSVCRT__errno() = MSVCRT_ERANGE;
2726 } else
2727 ret = ret*base + v;
2730 if(endptr && !empty)
2731 *endptr = (MSVCRT_wchar_t*)nptr;
2733 return negative ? -ret : ret;
2736 /*********************************************************************
2737 * _wcstoui64 (MSVCRT.@)
2739 unsigned __int64 CDECL MSVCRT__wcstoui64(const MSVCRT_wchar_t *nptr,
2740 MSVCRT_wchar_t **endptr, int base)
2742 return MSVCRT__wcstoui64_l(nptr, endptr, base, NULL);
2745 /*********************************************************************
2746 * _wcstoul_l (MSVCRT.@)
2748 MSVCRT_ulong __cdecl MSVCRT__wcstoul_l(const MSVCRT_wchar_t *s,
2749 MSVCRT_wchar_t **end, int base, MSVCRT__locale_t locale)
2751 __int64 ret = MSVCRT__wcstoi64_l(s, end, base, locale);
2753 if(ret > MSVCRT_ULONG_MAX) {
2754 ret = MSVCRT_ULONG_MAX;
2755 *MSVCRT__errno() = MSVCRT_ERANGE;
2756 }else if(ret < -(__int64)MSVCRT_ULONG_MAX) {
2757 ret = 1;
2758 *MSVCRT__errno() = MSVCRT_ERANGE;
2760 return ret;
2763 /*********************************************************************
2764 * wcstoul (MSVCRT.@)
2766 MSVCRT_ulong __cdecl MSVCRT_wcstoul(const MSVCRT_wchar_t *s, MSVCRT_wchar_t **end, int base)
2768 return MSVCRT__wcstoul_l(s, end, base, NULL);
2771 /******************************************************************
2772 * wcsnlen (MSVCRT.@)
2774 MSVCRT_size_t CDECL MSVCRT_wcsnlen(const MSVCRT_wchar_t *s, MSVCRT_size_t maxlen)
2776 MSVCRT_size_t i;
2778 for (i = 0; i < maxlen; i++)
2779 if (!s[i]) break;
2780 return i;
2783 /*********************************************************************
2784 * _towupper_l (MSVCRT.@)
2786 int CDECL MSVCRT__towupper_l(MSVCRT_wint_t c, MSVCRT__locale_t locale)
2788 MSVCRT_pthreadlocinfo locinfo;
2789 MSVCRT_wchar_t ret;
2791 if(!locale)
2792 locinfo = get_locinfo();
2793 else
2794 locinfo = locale->locinfo;
2796 if(!locinfo->lc_handle[MSVCRT_LC_CTYPE]) {
2797 if(c >= 'a' && c <= 'z')
2798 return c + 'A' - 'a';
2799 return c;
2802 if(!LCMapStringW(locinfo->lc_handle[MSVCRT_LC_CTYPE], LCMAP_UPPERCASE, &c, 1, &ret, 1))
2803 return c;
2804 return ret;
2807 /*********************************************************************
2808 * towupper (MSVCRT.@)
2810 int CDECL MSVCRT_towupper(MSVCRT_wint_t c)
2812 return MSVCRT__towupper_l(c, NULL);
2815 /*********************************************************************
2816 * wcschr (MSVCRT.@)
2818 MSVCRT_wchar_t* CDECL MSVCRT_wcschr(const MSVCRT_wchar_t *str, MSVCRT_wchar_t ch)
2820 do { if (*str == ch) return (WCHAR *)(ULONG_PTR)str; } while (*str++);
2821 return NULL;
2824 /*********************************************************************
2825 * wcsrchr (MSVCRT.@)
2827 MSVCRT_wchar_t* CDECL MSVCRT_wcsrchr(const MSVCRT_wchar_t *str, MSVCRT_wchar_t ch)
2829 WCHAR *ret = NULL;
2830 do { if (*str == ch) ret = (WCHAR *)(ULONG_PTR)str; } while (*str++);
2831 return ret;
2834 /***********************************************************************
2835 * wcslen (MSVCRT.@)
2837 MSVCRT_size_t CDECL MSVCRT_wcslen(const MSVCRT_wchar_t *str)
2839 const MSVCRT_wchar_t *s = str;
2840 while (*s) s++;
2841 return s - str;
2844 /*********************************************************************
2845 * wcsstr (MSVCRT.@)
2847 MSVCRT_wchar_t* CDECL MSVCRT_wcsstr(const MSVCRT_wchar_t *str, const MSVCRT_wchar_t *sub)
2849 while(*str)
2851 const MSVCRT_wchar_t *p1 = str, *p2 = sub;
2852 while(*p1 && *p2 && *p1 == *p2)
2854 p1++;
2855 p2++;
2857 if(!*p2)
2858 return (MSVCRT_wchar_t*)str;
2859 str++;
2861 return NULL;
2864 /*********************************************************************
2865 * _wtoi64_l (MSVCRT.@)
2867 __int64 CDECL MSVCRT__wtoi64_l(const MSVCRT_wchar_t *str, MSVCRT__locale_t locale)
2869 ULONGLONG RunningTotal = 0;
2870 BOOL bMinus = FALSE;
2872 while (MSVCRT__iswspace_l(*str, locale)) {
2873 str++;
2874 } /* while */
2876 if (*str == '+') {
2877 str++;
2878 } else if (*str == '-') {
2879 bMinus = TRUE;
2880 str++;
2881 } /* if */
2883 while (*str >= '0' && *str <= '9') {
2884 RunningTotal = RunningTotal * 10 + *str - '0';
2885 str++;
2886 } /* while */
2888 return bMinus ? -RunningTotal : RunningTotal;
2891 /*********************************************************************
2892 * _wtoi64 (MSVCRT.@)
2894 __int64 CDECL MSVCRT__wtoi64(const MSVCRT_wchar_t *str)
2896 return MSVCRT__wtoi64_l(str, NULL);
2899 /*********************************************************************
2900 * _wcsxfrm_l (MSVCRT.@)
2902 MSVCRT_size_t CDECL MSVCRT__wcsxfrm_l(MSVCRT_wchar_t *dest, const MSVCRT_wchar_t *src,
2903 MSVCRT_size_t len, MSVCRT__locale_t locale)
2905 MSVCRT_pthreadlocinfo locinfo;
2906 int i, ret;
2908 if(!MSVCRT_CHECK_PMT(src)) return INT_MAX;
2909 if(!MSVCRT_CHECK_PMT(dest || !len)) return INT_MAX;
2911 if(len > INT_MAX) {
2912 FIXME("len > INT_MAX not supported\n");
2913 len = INT_MAX;
2916 if(!locale)
2917 locinfo = get_locinfo();
2918 else
2919 locinfo = locale->locinfo;
2921 if(!locinfo->lc_handle[MSVCRT_LC_COLLATE]) {
2922 MSVCRT_wcsncpy(dest, src, len);
2923 return MSVCRT_wcslen(src);
2926 ret = LCMapStringW(locinfo->lc_handle[MSVCRT_LC_COLLATE],
2927 LCMAP_SORTKEY, src, -1, NULL, 0);
2928 if(!ret) {
2929 if(len) dest[0] = 0;
2930 *MSVCRT__errno() = MSVCRT_EILSEQ;
2931 return INT_MAX;
2933 if(!len) return ret-1;
2935 if(ret > len) {
2936 dest[0] = 0;
2937 *MSVCRT__errno() = MSVCRT_ERANGE;
2938 return ret-1;
2941 ret = LCMapStringW(locinfo->lc_handle[MSVCRT_LC_COLLATE],
2942 LCMAP_SORTKEY, src, -1, dest, len) - 1;
2943 for(i=ret; i>=0; i--)
2944 dest[i] = ((unsigned char*)dest)[i];
2945 return ret;
2948 /*********************************************************************
2949 * wcsxfrm (MSVCRT.@)
2951 MSVCRT_size_t CDECL MSVCRT_wcsxfrm(MSVCRT_wchar_t *dest,
2952 const MSVCRT_wchar_t *src, MSVCRT_size_t len)
2954 return MSVCRT__wcsxfrm_l(dest, src, len, NULL);