msvcrt: Don't forward towupper and towlower to ntdll.
[wine.git] / dlls / msvcrt / wcs.c
blob1968a2a0a5c6347eb76090e4c66f353a4f1c61f3
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/unicode.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
36 static BOOL n_format_enabled = TRUE;
38 #include "printf.h"
39 #define PRINTF_WIDE
40 #include "printf.h"
41 #undef PRINTF_WIDE
43 /* _get_printf_count_output - not exported in native msvcrt */
44 int CDECL MSVCRT__get_printf_count_output( void )
46 return n_format_enabled ? 1 : 0;
49 /* _set_printf_count_output - not exported in native msvcrt */
50 int CDECL MSVCRT__set_printf_count_output( int enable )
52 BOOL old = n_format_enabled;
53 n_format_enabled = enable != 0;
54 return old ? 1 : 0;
57 /*********************************************************************
58 * _wcsdup (MSVCRT.@)
60 MSVCRT_wchar_t* CDECL MSVCRT__wcsdup( const MSVCRT_wchar_t* str )
62 MSVCRT_wchar_t* ret = NULL;
63 if (str)
65 int size = (strlenW(str) + 1) * sizeof(MSVCRT_wchar_t);
66 ret = MSVCRT_malloc( size );
67 if (ret) memcpy( ret, str, size );
69 return ret;
72 /*********************************************************************
73 * _wcsicmp (MSVCRT.@)
75 INT CDECL MSVCRT__wcsicmp( const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2 )
77 return strcmpiW( str1, str2 );
80 /*********************************************************************
81 * _wcsicoll (MSVCRT.@)
83 INT CDECL MSVCRT__wcsicoll( const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2 )
85 return CompareStringW(get_locinfo()->lc_handle[MSVCRT_LC_COLLATE],
86 NORM_IGNORECASE, str1, -1, str2, -1)-CSTR_EQUAL;
89 /*********************************************************************
90 * _wcsnicoll (MSVCRT.@)
92 INT CDECL MSVCRT__wcsnicoll( const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2, MSVCRT_size_t count )
94 return CompareStringW(get_locinfo()->lc_handle[MSVCRT_LC_COLLATE],
95 NORM_IGNORECASE, str1, count, str2, count)-CSTR_EQUAL;
98 /*********************************************************************
99 * _wcsnset (MSVCRT.@)
101 MSVCRT_wchar_t* CDECL MSVCRT__wcsnset( MSVCRT_wchar_t* str, MSVCRT_wchar_t c, MSVCRT_size_t n )
103 MSVCRT_wchar_t* ret = str;
104 while ((n-- > 0) && *str) *str++ = c;
105 return ret;
108 /*********************************************************************
109 * _wcsrev (MSVCRT.@)
111 MSVCRT_wchar_t* CDECL MSVCRT__wcsrev( MSVCRT_wchar_t* str )
113 MSVCRT_wchar_t* ret = str;
114 MSVCRT_wchar_t* end = str + strlenW(str) - 1;
115 while (end > str)
117 MSVCRT_wchar_t t = *end;
118 *end-- = *str;
119 *str++ = t;
121 return ret;
124 /*********************************************************************
125 * _wcsset (MSVCRT.@)
127 MSVCRT_wchar_t* CDECL MSVCRT__wcsset( MSVCRT_wchar_t* str, MSVCRT_wchar_t c )
129 MSVCRT_wchar_t* ret = str;
130 while (*str) *str++ = c;
131 return ret;
134 /******************************************************************
135 * _wcsupr_s_l (MSVCRT.@)
137 int CDECL MSVCRT__wcsupr_s_l( MSVCRT_wchar_t* str, MSVCRT_size_t n,
138 MSVCRT__locale_t locale )
140 MSVCRT_wchar_t* ptr = str;
142 if (!str || !n)
144 if (str) *str = '\0';
145 *MSVCRT__errno() = MSVCRT_EINVAL;
146 return MSVCRT_EINVAL;
149 while (n--)
151 if (!*ptr) return 0;
152 /* FIXME: add locale support */
153 *ptr = toupperW(*ptr);
154 ptr++;
157 /* MSDN claims that the function should return and set errno to
158 * ERANGE, which doesn't seem to be true based on the tests. */
159 *str = '\0';
160 *MSVCRT__errno() = MSVCRT_EINVAL;
161 return MSVCRT_EINVAL;
164 /******************************************************************
165 * _wcsupr_s (MSVCRT.@)
168 INT CDECL MSVCRT__wcsupr_s( MSVCRT_wchar_t* str, MSVCRT_size_t n )
170 return MSVCRT__wcsupr_s_l( str, n, NULL );
173 /******************************************************************
174 * _wcslwr_s (MSVCRT.@)
176 int CDECL MSVCRT__wcslwr_s( MSVCRT_wchar_t* str, MSVCRT_size_t n )
178 MSVCRT_wchar_t* ptr = str;
180 if (!str || !n)
182 if (str) *str = '\0';
183 *MSVCRT__errno() = MSVCRT_EINVAL;
184 return MSVCRT_EINVAL;
187 while (n--)
189 if (!*ptr) return 0;
190 *ptr = tolowerW(*ptr);
191 ptr++;
194 /* MSDN claims that the function should return and set errno to
195 * ERANGE, which doesn't seem to be true based on the tests. */
196 *str = '\0';
197 *MSVCRT__errno() = MSVCRT_EINVAL;
198 return MSVCRT_EINVAL;
201 /*********************************************************************
202 * _wcstod_l - not exported in native msvcrt
204 double CDECL MSVCRT__wcstod_l(const MSVCRT_wchar_t* str, MSVCRT_wchar_t** end,
205 MSVCRT__locale_t locale)
207 MSVCRT_pthreadlocinfo locinfo;
208 unsigned __int64 d=0, hlp;
209 unsigned fpcontrol;
210 int exp=0, sign=1;
211 const MSVCRT_wchar_t *p;
212 double ret;
213 long double lret=1, expcnt = 10;
214 BOOL found_digit = FALSE, negexp;
216 if (!MSVCRT_CHECK_PMT(str != NULL)) return 0;
218 if(!locale)
219 locinfo = get_locinfo();
220 else
221 locinfo = locale->locinfo;
223 p = str;
224 while(isspaceW(*p))
225 p++;
227 if(*p == '-') {
228 sign = -1;
229 p++;
230 } else if(*p == '+')
231 p++;
233 while(isdigitW(*p)) {
234 found_digit = TRUE;
235 hlp = d*10+*(p++)-'0';
236 if(d>MSVCRT_UI64_MAX/10 || hlp<d) {
237 exp++;
238 break;
239 } else
240 d = hlp;
242 while(isdigitW(*p)) {
243 exp++;
244 p++;
246 if(*p == *locinfo->lconv->decimal_point)
247 p++;
249 while(isdigitW(*p)) {
250 found_digit = TRUE;
251 hlp = d*10+*(p++)-'0';
252 if(d>MSVCRT_UI64_MAX/10 || hlp<d)
253 break;
255 d = hlp;
256 exp--;
258 while(isdigitW(*p))
259 p++;
261 if(!found_digit) {
262 if(end)
263 *end = (MSVCRT_wchar_t*)str;
264 return 0.0;
267 if(*p=='e' || *p=='E' || *p=='d' || *p=='D') {
268 int e=0, s=1;
270 p++;
271 if(*p == '-') {
272 s = -1;
273 p++;
274 } else if(*p == '+')
275 p++;
277 if(isdigitW(*p)) {
278 while(isdigitW(*p)) {
279 if(e>INT_MAX/10 || (e=e*10+*p-'0')<0)
280 e = INT_MAX;
281 p++;
283 e *= s;
285 if(exp<0 && e<0 && exp+e>=0) exp = INT_MIN;
286 else if(exp>0 && e>0 && exp+e<0) exp = INT_MAX;
287 else exp += e;
288 } else {
289 if(*p=='-' || *p=='+')
290 p--;
291 p--;
295 fpcontrol = _control87(0, 0);
296 _control87(MSVCRT__EM_DENORMAL|MSVCRT__EM_INVALID|MSVCRT__EM_ZERODIVIDE
297 |MSVCRT__EM_OVERFLOW|MSVCRT__EM_UNDERFLOW|MSVCRT__EM_INEXACT, 0xffffffff);
299 negexp = (exp < 0);
300 if(negexp)
301 exp = -exp;
302 while(exp) {
303 if(exp & 1)
304 lret *= expcnt;
305 exp /= 2;
306 expcnt = expcnt*expcnt;
308 ret = (long double)sign * (negexp ? d/lret : d*lret);
310 _control87(fpcontrol, 0xffffffff);
312 if((d && ret==0.0) || isinf(ret))
313 *MSVCRT__errno() = MSVCRT_ERANGE;
315 if(end)
316 *end = (MSVCRT_wchar_t*)p;
318 return ret;
321 /*********************************************************************
322 * wcsrtombs_l (INTERNAL)
324 static MSVCRT_size_t CDECL MSVCRT_wcsrtombs_l(char *mbstr, const MSVCRT_wchar_t **wcstr,
325 MSVCRT_size_t count, MSVCRT__locale_t locale)
327 MSVCRT_pthreadlocinfo locinfo;
328 MSVCRT_size_t tmp = 0;
329 BOOL used_default;
331 if(!locale)
332 locinfo = get_locinfo();
333 else
334 locinfo = locale->locinfo;
336 if(!mbstr) {
337 tmp = WideCharToMultiByte(locinfo->lc_codepage, WC_NO_BEST_FIT_CHARS,
338 *wcstr, -1, NULL, 0, NULL, &used_default)-1;
339 if(used_default)
340 return -1;
341 return tmp;
344 while(**wcstr) {
345 char buf[3];
346 MSVCRT_size_t i, size;
348 size = WideCharToMultiByte(locinfo->lc_codepage, WC_NO_BEST_FIT_CHARS,
349 *wcstr, 1, buf, 3, NULL, &used_default);
350 if(used_default)
351 return -1;
352 if(tmp+size > count)
353 return tmp;
355 for(i=0; i<size; i++)
356 mbstr[tmp++] = buf[i];
357 (*wcstr)++;
360 if(tmp < count) {
361 mbstr[tmp] = '\0';
362 *wcstr = NULL;
364 return tmp;
367 /*********************************************************************
368 * _wcstombs_l (MSVCRT.@)
370 MSVCRT_size_t CDECL MSVCRT__wcstombs_l(char *mbstr, const MSVCRT_wchar_t *wcstr,
371 MSVCRT_size_t count, MSVCRT__locale_t locale)
373 return MSVCRT_wcsrtombs_l(mbstr, &wcstr, count, locale);
376 /*********************************************************************
377 * wcstombs (MSVCRT.@)
379 MSVCRT_size_t CDECL MSVCRT_wcstombs(char *mbstr, const MSVCRT_wchar_t *wcstr,
380 MSVCRT_size_t count)
382 return MSVCRT_wcsrtombs_l(mbstr, &wcstr, count, NULL);
385 /*********************************************************************
386 * wcsrtombs (MSVCRT.@)
388 MSVCRT_size_t CDECL MSVCRT_wcsrtombs(char *mbstr, const MSVCRT_wchar_t **wcstr,
389 MSVCRT_size_t count, MSVCRT_mbstate_t *mbstate)
391 if(mbstate)
392 *mbstate = 0;
394 return MSVCRT_wcsrtombs_l(mbstr, wcstr, count, NULL);
397 /*********************************************************************
398 * MSVCRT_wcsrtombs_s_l (INTERNAL)
400 static int MSVCRT_wcsrtombs_s_l(MSVCRT_size_t *ret, char *mbstr,
401 MSVCRT_size_t size, const MSVCRT_wchar_t **wcstr,
402 MSVCRT_size_t count, MSVCRT__locale_t locale)
404 MSVCRT_size_t conv;
406 if(!mbstr && !size && wcstr) {
407 conv = MSVCRT_wcsrtombs_l(NULL, wcstr, 0, locale);
408 if(ret)
409 *ret = conv+1;
410 return 0;
413 if (!MSVCRT_CHECK_PMT(mbstr != NULL)) return MSVCRT_EINVAL;
414 if (size) mbstr[0] = '\0';
415 if (!MSVCRT_CHECK_PMT(wcstr != NULL)) return MSVCRT_EINVAL;
416 if (!MSVCRT_CHECK_PMT(*wcstr != NULL)) return MSVCRT_EINVAL;
418 if(count==MSVCRT__TRUNCATE || size<count)
419 conv = size;
420 else
421 conv = count;
423 conv = MSVCRT_wcsrtombs_l(mbstr, wcstr, conv, locale);
424 if(conv<size)
425 mbstr[conv++] = '\0';
426 else if(conv==size && (count==MSVCRT__TRUNCATE || mbstr[conv-1]=='\0'))
427 mbstr[conv-1] = '\0';
428 else {
429 MSVCRT_INVALID_PMT("mbstr[size] is too small", MSVCRT_ERANGE);
430 if(size)
431 mbstr[0] = '\0';
432 return MSVCRT_ERANGE;
435 if(ret)
436 *ret = conv;
437 return 0;
440 /*********************************************************************
441 * _wcstombs_s_l (MSVCRT.@)
443 int CDECL MSVCRT__wcstombs_s_l(MSVCRT_size_t *ret, char *mbstr,
444 MSVCRT_size_t size, const MSVCRT_wchar_t *wcstr,
445 MSVCRT_size_t count, MSVCRT__locale_t locale)
447 return MSVCRT_wcsrtombs_s_l(ret, mbstr, size, &wcstr,count, locale);
450 /*********************************************************************
451 * wcstombs_s (MSVCRT.@)
453 int CDECL MSVCRT_wcstombs_s(MSVCRT_size_t *ret, char *mbstr,
454 MSVCRT_size_t size, const MSVCRT_wchar_t *wcstr, MSVCRT_size_t count)
456 return MSVCRT_wcsrtombs_s_l(ret, mbstr, size, &wcstr, count, NULL);
459 /*********************************************************************
460 * wcsrtombs_s (MSVCRT.@)
462 int CDECL MSVCRT_wcsrtombs_s(MSVCRT_size_t *ret, char *mbstr, MSVCRT_size_t size,
463 const MSVCRT_wchar_t **wcstr, MSVCRT_size_t count, MSVCRT_mbstate_t *mbstate)
465 if(mbstate)
466 *mbstate = 0;
468 return MSVCRT_wcsrtombs_s_l(ret, mbstr, size, wcstr, count, NULL);
471 /*********************************************************************
472 * wcstod (MSVCRT.@)
474 double CDECL MSVCRT_wcstod(const MSVCRT_wchar_t* lpszStr, MSVCRT_wchar_t** end)
476 return MSVCRT__wcstod_l(lpszStr, end, NULL);
479 /*********************************************************************
480 * _wtof (MSVCRT.@)
482 double CDECL MSVCRT__wtof(const MSVCRT_wchar_t *str)
484 return MSVCRT__wcstod_l(str, NULL, NULL);
487 /*********************************************************************
488 * _wtof_l (MSVCRT.@)
490 double CDECL MSVCRT__wtof_l(const MSVCRT_wchar_t *str, MSVCRT__locale_t locale)
492 return MSVCRT__wcstod_l(str, NULL, locale);
495 /*********************************************************************
496 * arg_clbk_valist (INTERNAL)
498 printf_arg arg_clbk_valist(void *ctx, int arg_pos, int type, __ms_va_list *valist)
500 printf_arg ret;
502 if(type == VT_I8)
503 ret.get_longlong = va_arg(*valist, LONGLONG);
504 else if(type == VT_INT)
505 ret.get_int = va_arg(*valist, int);
506 else if(type == VT_R8)
507 ret.get_double = va_arg(*valist, double);
508 else if(type == VT_PTR)
509 ret.get_ptr = va_arg(*valist, void*);
510 else {
511 ERR("Incorrect type\n");
512 ret.get_int = 0;
515 return ret;
518 /*********************************************************************
519 * arg_clbk_positional (INTERNAL)
521 static printf_arg arg_clbk_positional(void *ctx, int pos, int type, __ms_va_list *valist)
523 printf_arg *args = ctx;
524 return args[pos];
527 /*********************************************************************
528 * _vsnprintf (MSVCRT.@)
530 int CDECL MSVCRT_vsnprintf( char *str, MSVCRT_size_t len,
531 const char *format, __ms_va_list valist )
533 static const char nullbyte = '\0';
534 struct _str_ctx_a ctx = {len, str};
535 int ret;
537 ret = pf_printf_a(puts_clbk_str_a, &ctx, format, NULL, FALSE, FALSE,
538 arg_clbk_valist, NULL, &valist);
539 puts_clbk_str_a(&ctx, 1, &nullbyte);
540 return ret;
543 /*********************************************************************
544 * _vsnprintf_l (MSVCRT.@)
546 int CDECL MSVCRT_vsnprintf_l( char *str, MSVCRT_size_t len, const char *format,
547 MSVCRT__locale_t locale, __ms_va_list valist )
549 static const char nullbyte = '\0';
550 struct _str_ctx_a ctx = {len, str};
551 int ret;
553 ret = pf_printf_a(puts_clbk_str_a, &ctx, format, locale, FALSE, FALSE,
554 arg_clbk_valist, NULL, &valist);
555 puts_clbk_str_a(&ctx, 1, &nullbyte);
556 return ret;
559 /*********************************************************************
560 * _vsnprintf_s_l (MSVCRT.@)
562 int CDECL MSVCRT_vsnprintf_s_l( char *str, MSVCRT_size_t sizeOfBuffer,
563 MSVCRT_size_t count, const char *format,
564 MSVCRT__locale_t locale, __ms_va_list valist )
566 static const char nullbyte = '\0';
567 struct _str_ctx_a ctx;
568 int len, ret;
570 if(sizeOfBuffer<count+1 || count==-1)
571 len = sizeOfBuffer;
572 else
573 len = count+1;
575 ctx.len = len;
576 ctx.buf = str;
577 ret = pf_printf_a(puts_clbk_str_a, &ctx, format, locale, FALSE, TRUE,
578 arg_clbk_valist, NULL, &valist);
579 puts_clbk_str_a(&ctx, 1, &nullbyte);
581 if(ret<0 || ret==len) {
582 if(count!=MSVCRT__TRUNCATE && count>sizeOfBuffer) {
583 MSVCRT_INVALID_PMT("str[sizeOfBuffer] is too small", MSVCRT_ERANGE);
584 memset(str, 0, sizeOfBuffer);
585 } else
586 str[len-1] = '\0';
588 return -1;
591 return ret;
594 /*********************************************************************
595 * _vsnprintf_s (MSVCRT.@)
597 int CDECL MSVCRT_vsnprintf_s( char *str, MSVCRT_size_t sizeOfBuffer,
598 MSVCRT_size_t count, const char *format, __ms_va_list valist )
600 return MSVCRT_vsnprintf_s_l(str,sizeOfBuffer, count, format, NULL, valist);
603 /*********************************************************************
604 * vsprintf (MSVCRT.@)
606 int CDECL MSVCRT_vsprintf( char *str, const char *format, __ms_va_list valist)
608 return MSVCRT_vsnprintf(str, INT_MAX, format, valist);
611 /*********************************************************************
612 * vsprintf_s (MSVCRT.@)
614 int CDECL MSVCRT_vsprintf_s( char *str, MSVCRT_size_t num, const char *format, __ms_va_list valist)
616 return MSVCRT_vsnprintf(str, num, format, valist);
619 /*********************************************************************
620 * _vscprintf (MSVCRT.@)
622 int CDECL MSVCRT__vscprintf( const char *format, __ms_va_list valist )
624 return MSVCRT_vsnprintf( NULL, INT_MAX, format, valist );
627 /*********************************************************************
628 * _snprintf (MSVCRT.@)
630 int CDECL MSVCRT__snprintf(char *str, unsigned int len, const char *format, ...)
632 int retval;
633 __ms_va_list valist;
634 __ms_va_start(valist, format);
635 retval = MSVCRT_vsnprintf(str, len, format, valist);
636 __ms_va_end(valist);
637 return retval;
640 /*********************************************************************
641 * _snprintf_s (MSVCRT.@)
643 int CDECL MSVCRT__snprintf_s(char *str, unsigned int len, unsigned int count,
644 const char *format, ...)
646 int retval;
647 __ms_va_list valist;
648 __ms_va_start(valist, format);
649 retval = MSVCRT_vsnprintf_s_l(str, len, count, format, NULL, valist);
650 __ms_va_end(valist);
651 return retval;
654 /*********************************************************************
655 * _scprintf (MSVCRT.@)
657 int CDECL MSVCRT__scprintf(const char *format, ...)
659 int retval;
660 __ms_va_list valist;
661 __ms_va_start(valist, format);
662 retval = MSVCRT__vscprintf(format, valist);
663 __ms_va_end(valist);
664 return retval;
667 /*********************************************************************
668 * _vsnwprintf (MSVCRT.@)
670 int CDECL MSVCRT_vsnwprintf(MSVCRT_wchar_t *str, MSVCRT_size_t len,
671 const MSVCRT_wchar_t *format, __ms_va_list valist)
673 static const MSVCRT_wchar_t nullbyte = '\0';
674 struct _str_ctx_w ctx = {len, str};
675 int ret;
677 ret = pf_printf_w(puts_clbk_str_w, &ctx, format, NULL, FALSE, FALSE,
678 arg_clbk_valist, NULL, &valist);
679 puts_clbk_str_w(&ctx, 1, &nullbyte);
680 return ret;
683 /*********************************************************************
684 * _vsnwprintf_l (MSVCRT.@)
686 int CDECL MSVCRT_vsnwprintf_l(MSVCRT_wchar_t *str, MSVCRT_size_t len,
687 const MSVCRT_wchar_t *format, MSVCRT__locale_t locale,
688 __ms_va_list valist)
690 static const MSVCRT_wchar_t nullbyte = '\0';
691 struct _str_ctx_w ctx = {len, str};
692 int ret;
694 ret = pf_printf_w(puts_clbk_str_w, &ctx, format, locale, FALSE, FALSE,
695 arg_clbk_valist, NULL, &valist);
696 puts_clbk_str_w(&ctx, 1, &nullbyte);
697 return ret;
700 /*********************************************************************
701 * _vswprintf_p_l (MSVCRT.@)
703 int CDECL MSVCRT_vswprintf_p_l(MSVCRT_wchar_t *buffer, MSVCRT_size_t length,
704 const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, __ms_va_list args)
706 static const MSVCRT_wchar_t nullbyte = '\0';
707 printf_arg args_ctx[MSVCRT__ARGMAX+1];
708 struct _str_ctx_w puts_ctx = {length, buffer};
709 int ret;
711 memset(args_ctx, 0, sizeof(args_ctx));
713 ret = create_positional_ctx_w(args_ctx, format, args);
714 if(ret < 0) {
715 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
716 *MSVCRT__errno() = MSVCRT_EINVAL;
717 return ret;
718 } else if(ret == 0)
719 ret = pf_printf_w(puts_clbk_str_w, &puts_ctx, format, locale, FALSE, TRUE,
720 arg_clbk_valist, NULL, &args);
721 else
722 ret = pf_printf_w(puts_clbk_str_w, &puts_ctx, format, locale, TRUE, TRUE,
723 arg_clbk_positional, args_ctx, NULL);
725 puts_clbk_str_w(&puts_ctx, 1, &nullbyte);
726 return ret;
729 /*********************************************************************
730 * _vsnwprintf_s_l (MSVCRT.@)
732 int CDECL MSVCRT_vsnwprintf_s_l( MSVCRT_wchar_t *str, MSVCRT_size_t sizeOfBuffer,
733 MSVCRT_size_t count, const MSVCRT_wchar_t *format,
734 MSVCRT__locale_t locale, __ms_va_list valist)
736 static const MSVCRT_wchar_t nullbyte = '\0';
737 struct _str_ctx_w ctx;
738 int len, ret;
740 len = sizeOfBuffer;
741 if(count!=-1 && len>count+1)
742 len = count+1;
744 ctx.len = len;
745 ctx.buf = str;
746 ret = pf_printf_w(puts_clbk_str_w, &ctx, format, locale, FALSE, TRUE,
747 arg_clbk_valist, NULL, &valist);
748 puts_clbk_str_w(&ctx, 1, &nullbyte);
750 if(ret<0 || ret==len) {
751 if(count!=MSVCRT__TRUNCATE && count>sizeOfBuffer) {
752 MSVCRT_INVALID_PMT("str[sizeOfBuffer] is too small", MSVCRT_ERANGE);
753 memset(str, 0, sizeOfBuffer*sizeof(MSVCRT_wchar_t));
754 } else
755 str[len-1] = '\0';
757 return -1;
760 return ret;
763 /*********************************************************************
764 * _vsnwprintf_s (MSVCRT.@)
766 int CDECL MSVCRT_vsnwprintf_s(MSVCRT_wchar_t *str, MSVCRT_size_t sizeOfBuffer,
767 MSVCRT_size_t count, const MSVCRT_wchar_t *format, __ms_va_list valist)
769 return MSVCRT_vsnwprintf_s_l(str, sizeOfBuffer, count,
770 format, NULL, valist);
773 /*********************************************************************
774 * _snwprintf (MSVCRT.@)
776 int CDECL MSVCRT__snwprintf( MSVCRT_wchar_t *str, unsigned int len, const MSVCRT_wchar_t *format, ...)
778 int retval;
779 __ms_va_list valist;
780 __ms_va_start(valist, format);
781 retval = MSVCRT_vsnwprintf(str, len, format, valist);
782 __ms_va_end(valist);
783 return retval;
786 /*********************************************************************
787 * _snwprintf_l (MSVCRT.@)
789 int CDECL MSVCRT__snwprintf_l( MSVCRT_wchar_t *str, unsigned int len, const MSVCRT_wchar_t *format,
790 MSVCRT__locale_t locale, ...)
792 int retval;
793 __ms_va_list valist;
794 __ms_va_start(valist, locale);
795 retval = MSVCRT_vsnwprintf_l(str, len, format, locale, valist);
796 __ms_va_end(valist);
797 return retval;
800 /*********************************************************************
801 * _snwprintf_s (MSVCRT.@)
803 int CDECL MSVCRT__snwprintf_s( MSVCRT_wchar_t *str, unsigned int len, unsigned int count,
804 const MSVCRT_wchar_t *format, ...)
806 int retval;
807 __ms_va_list valist;
808 __ms_va_start(valist, format);
809 retval = MSVCRT_vsnwprintf_s_l(str, len, count, format, NULL, valist);
810 __ms_va_end(valist);
811 return retval;
814 /*********************************************************************
815 * sprintf (MSVCRT.@)
817 int CDECL MSVCRT_sprintf( char *str, const char *format, ... )
819 __ms_va_list ap;
820 int r;
822 __ms_va_start( ap, format );
823 r = MSVCRT_vsnprintf( str, INT_MAX, format, ap );
824 __ms_va_end( ap );
825 return r;
828 /*********************************************************************
829 * sprintf_s (MSVCRT.@)
831 int CDECL MSVCRT_sprintf_s( char *str, MSVCRT_size_t num, const char *format, ... )
833 __ms_va_list ap;
834 int r;
836 __ms_va_start( ap, format );
837 r = MSVCRT_vsnprintf( str, num, format, ap );
838 __ms_va_end( ap );
839 return r;
842 /*********************************************************************
843 * _scwprintf (MSVCRT.@)
845 int CDECL MSVCRT__scwprintf( const MSVCRT_wchar_t *format, ... )
847 __ms_va_list ap;
848 int r;
850 __ms_va_start( ap, format );
851 r = MSVCRT_vsnwprintf( NULL, INT_MAX, format, ap );
852 __ms_va_end( ap );
853 return r;
856 /*********************************************************************
857 * swprintf (MSVCRT.@)
859 int CDECL MSVCRT_swprintf( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *format, ... )
861 __ms_va_list ap;
862 int r;
864 __ms_va_start( ap, format );
865 r = MSVCRT_vsnwprintf( str, INT_MAX, format, ap );
866 __ms_va_end( ap );
867 return r;
870 /*********************************************************************
871 * swprintf_s (MSVCRT.@)
873 int CDECL MSVCRT_swprintf_s(MSVCRT_wchar_t *str, MSVCRT_size_t numberOfElements,
874 const MSVCRT_wchar_t *format, ... )
876 __ms_va_list ap;
877 int r;
879 __ms_va_start(ap, format);
880 r = MSVCRT_vsnwprintf_s(str, numberOfElements, INT_MAX, format, ap);
881 __ms_va_end(ap);
883 return r;
886 /*********************************************************************
887 * _vswprintf (MSVCRT.@)
889 int CDECL MSVCRT_vswprintf( MSVCRT_wchar_t* str, const MSVCRT_wchar_t* format, __ms_va_list args )
891 return MSVCRT_vsnwprintf( str, INT_MAX, format, args );
894 /*********************************************************************
895 * _vswprintf (MSVCRT.@)
897 int CDECL MSVCRT_vswprintf_l( MSVCRT_wchar_t* str, const MSVCRT_wchar_t* format,
898 MSVCRT__locale_t locale, __ms_va_list args )
900 return MSVCRT_vsnwprintf_l( str, INT_MAX, format, locale, args );
903 /*********************************************************************
904 * _vscwprintf (MSVCRT.@)
906 int CDECL MSVCRT__vscwprintf( const MSVCRT_wchar_t *format, __ms_va_list args )
908 return MSVCRT_vsnwprintf( NULL, INT_MAX, format, args );
911 /*********************************************************************
912 * _vscwprintf_l (MSVCRT.@)
914 int CDECL MSVCRT__vscwprintf_l( const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, __ms_va_list args )
916 return MSVCRT_vsnwprintf_l( NULL, INT_MAX, format, locale, args );
919 /*********************************************************************
920 * _vscwprintf_p_l (MSVCRT.@)
922 int CDECL MSVCRT__vscwprintf_p_l( const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, __ms_va_list args )
924 return MSVCRT_vswprintf_p_l( NULL, INT_MAX, format, locale, args );
927 /*********************************************************************
928 * vswprintf_s (MSVCRT.@)
930 int CDECL MSVCRT_vswprintf_s(MSVCRT_wchar_t* str, MSVCRT_size_t numberOfElements,
931 const MSVCRT_wchar_t* format, __ms_va_list args)
933 return MSVCRT_vsnwprintf_s(str, numberOfElements, INT_MAX, format, args );
936 /*********************************************************************
937 * _vswprintf_s_l (MSVCRT.@)
939 int CDECL MSVCRT_vswprintf_s_l(MSVCRT_wchar_t* str, MSVCRT_size_t numberOfElements,
940 const MSVCRT_wchar_t* format, MSVCRT__locale_t locale, __ms_va_list args)
942 return MSVCRT_vsnwprintf_s_l(str, numberOfElements, INT_MAX,
943 format, locale, args );
946 /*********************************************************************
947 * _vsprintf_p_l (MSVCRT.@)
949 int CDECL MSVCRT_vsprintf_p_l(char *buffer, MSVCRT_size_t length, const char *format,
950 MSVCRT__locale_t locale, __ms_va_list args)
952 static const char nullbyte = '\0';
953 printf_arg args_ctx[MSVCRT__ARGMAX+1];
954 struct _str_ctx_a puts_ctx = {length, buffer};
955 int ret;
957 memset(args_ctx, 0, sizeof(args_ctx));
959 ret = create_positional_ctx_a(args_ctx, format, args);
960 if(ret < 0) {
961 MSVCRT__invalid_parameter(NULL, NULL, NULL, 0, 0);
962 *MSVCRT__errno() = MSVCRT_EINVAL;
963 return ret;
964 } else if(ret == 0)
965 ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale, FALSE, TRUE,
966 arg_clbk_valist, NULL, &args);
967 else
968 ret = pf_printf_a(puts_clbk_str_a, &puts_ctx, format, locale, TRUE, TRUE,
969 arg_clbk_positional, args_ctx, NULL);
971 puts_clbk_str_a(&puts_ctx, 1, &nullbyte);
972 return ret;
975 /*********************************************************************
976 * _vsprintf_p (MSVCRT.@)
978 int CDECL MSVCRT_vsprintf_p(char *buffer, MSVCRT_size_t length,
979 const char *format, __ms_va_list args)
981 return MSVCRT_vsprintf_p_l(buffer, length, format, NULL, args);
984 /*********************************************************************
985 * _sprintf_p_l (MSVCRT.@)
987 int CDECL MSVCRT_sprintf_p_l(char *buffer, MSVCRT_size_t length,
988 const char *format, MSVCRT__locale_t locale, ...)
990 __ms_va_list valist;
991 int r;
993 __ms_va_start(valist, locale);
994 r = MSVCRT_vsprintf_p_l(buffer, length, format, locale, valist);
995 __ms_va_end(valist);
997 return r;
1000 /*********************************************************************
1001 * _swprintf_p_l (MSVCRT.@)
1003 int CDECL MSVCRT_swprintf_p_l(MSVCRT_wchar_t *buffer, MSVCRT_size_t length,
1004 const MSVCRT_wchar_t *format, MSVCRT__locale_t locale, ...)
1006 __ms_va_list valist;
1007 int r;
1009 __ms_va_start(valist, locale);
1010 r = MSVCRT_vswprintf_p_l(buffer, length, format, locale, valist);
1011 __ms_va_end(valist);
1013 return r;
1016 /*********************************************************************
1017 * wcscoll (MSVCRT.@)
1019 int CDECL MSVCRT_wcscoll( const MSVCRT_wchar_t* str1, const MSVCRT_wchar_t* str2 )
1021 return CompareStringW(get_locinfo()->lc_handle[MSVCRT_LC_COLLATE],
1022 0, str1, -1, str2, -1)-CSTR_EQUAL;
1025 /*********************************************************************
1026 * wcspbrk (MSVCRT.@)
1028 MSVCRT_wchar_t* CDECL MSVCRT_wcspbrk( const MSVCRT_wchar_t* str, const MSVCRT_wchar_t* accept )
1030 const MSVCRT_wchar_t* p;
1032 while (*str)
1034 for (p = accept; *p; p++) if (*p == *str) return (MSVCRT_wchar_t*)str;
1035 str++;
1037 return NULL;
1040 /*********************************************************************
1041 * wcstok_s (MSVCRT.@)
1043 MSVCRT_wchar_t * CDECL wcstok_s( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *delim,
1044 MSVCRT_wchar_t **next_token )
1046 MSVCRT_wchar_t *ret;
1048 if (!MSVCRT_CHECK_PMT(delim != NULL)) return NULL;
1049 if (!MSVCRT_CHECK_PMT(next_token != NULL)) return NULL;
1050 if (!MSVCRT_CHECK_PMT(str != NULL || *next_token != NULL)) return NULL;
1052 if (!str) str = *next_token;
1054 while (*str && strchrW( delim, *str )) str++;
1055 if (!*str) return NULL;
1056 ret = str++;
1057 while (*str && !strchrW( delim, *str )) str++;
1058 if (*str) *str++ = 0;
1059 *next_token = str;
1060 return ret;
1063 /*********************************************************************
1064 * wcstok (MSVCRT.@)
1066 MSVCRT_wchar_t * CDECL MSVCRT_wcstok( MSVCRT_wchar_t *str, const MSVCRT_wchar_t *delim )
1068 return wcstok_s(str, delim, &msvcrt_get_thread_data()->wcstok_next);
1071 /*********************************************************************
1072 * wctob (MSVCRT.@)
1074 INT CDECL MSVCRT_wctob( MSVCRT_wint_t wchar )
1076 char out;
1077 BOOL error;
1078 UINT codepage = get_locinfo()->lc_codepage;
1080 if(!codepage) {
1081 if (wchar < 0xff)
1082 return (signed char)wchar;
1083 else
1084 return MSVCRT_EOF;
1085 } else if(WideCharToMultiByte( codepage, 0, &wchar, 1, &out, 1, NULL, &error ) && !error)
1086 return (INT)out;
1087 return MSVCRT_EOF;
1090 /*********************************************************************
1091 * wctomb (MSVCRT.@)
1093 INT CDECL MSVCRT_wctomb( char *dst, MSVCRT_wchar_t ch )
1095 BOOL error;
1096 INT size;
1098 size = WideCharToMultiByte(get_locinfo()->lc_codepage, 0, &ch, 1, dst, dst ? 6 : 0, NULL, &error);
1099 if(!size || error) {
1100 *MSVCRT__errno() = MSVCRT_EINVAL;
1101 return MSVCRT_EOF;
1103 return size;
1106 /*********************************************************************
1107 * wcrtomb (MSVCRT.@)
1109 MSVCRT_size_t CDECL MSVCRT_wcrtomb( char *dst, MSVCRT_wchar_t ch, MSVCRT_mbstate_t *s)
1111 if(s)
1112 *s = 0;
1113 return MSVCRT_wctomb(dst, ch);
1116 /*********************************************************************
1117 * iswalnum (MSVCRT.@)
1119 INT CDECL MSVCRT_iswalnum( MSVCRT_wchar_t wc )
1121 return isalnumW( wc );
1124 /*********************************************************************
1125 * iswalpha (MSVCRT.@)
1127 INT CDECL MSVCRT_iswalpha( MSVCRT_wchar_t wc )
1129 return isalphaW( wc );
1132 /*********************************************************************
1133 * iswalpha_l (MSVCRT.@)
1135 INT CDECL MSVCRT__iswalpha_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
1137 return isalphaW( wc );
1140 /*********************************************************************
1141 * iswcntrl (MSVCRT.@)
1143 INT CDECL MSVCRT_iswcntrl( MSVCRT_wchar_t wc )
1145 return iscntrlW( wc );
1148 /*********************************************************************
1149 * iswdigit (MSVCRT.@)
1151 INT CDECL MSVCRT_iswdigit( MSVCRT_wchar_t wc )
1153 return isdigitW( wc );
1156 /*********************************************************************
1157 * _iswdigit_l (MSVCRT.@)
1159 INT CDECL MSVCRT__iswdigit_l( MSVCRT_wchar_t wc, MSVCRT__locale_t locale )
1161 return isdigitW( wc );
1164 /*********************************************************************
1165 * iswgraph (MSVCRT.@)
1167 INT CDECL MSVCRT_iswgraph( MSVCRT_wchar_t wc )
1169 return isgraphW( wc );
1172 /*********************************************************************
1173 * iswlower (MSVCRT.@)
1175 INT CDECL MSVCRT_iswlower( MSVCRT_wchar_t wc )
1177 return islowerW( wc );
1180 /*********************************************************************
1181 * iswprint (MSVCRT.@)
1183 INT CDECL MSVCRT_iswprint( MSVCRT_wchar_t wc )
1185 return isprintW( wc );
1188 /*********************************************************************
1189 * iswpunct (MSVCRT.@)
1191 INT CDECL MSVCRT_iswpunct( MSVCRT_wchar_t wc )
1193 return ispunctW( wc );
1196 /*********************************************************************
1197 * iswspace (MSVCRT.@)
1199 INT CDECL MSVCRT_iswspace( MSVCRT_wchar_t wc )
1201 return isspaceW( wc );
1204 /*********************************************************************
1205 * iswupper (MSVCRT.@)
1207 INT CDECL MSVCRT_iswupper( MSVCRT_wchar_t wc )
1209 return isupperW( wc );
1212 /*********************************************************************
1213 * iswxdigit (MSVCRT.@)
1215 INT CDECL MSVCRT_iswxdigit( MSVCRT_wchar_t wc )
1217 return isxdigitW( wc );
1220 /*********************************************************************
1221 * wcscpy_s (MSVCRT.@)
1223 INT CDECL MSVCRT_wcscpy_s( MSVCRT_wchar_t* wcDest, MSVCRT_size_t numElement, const MSVCRT_wchar_t *wcSrc)
1225 MSVCRT_size_t size = 0;
1227 if(!wcDest || !numElement)
1228 return MSVCRT_EINVAL;
1230 wcDest[0] = 0;
1232 if(!wcSrc)
1234 return MSVCRT_EINVAL;
1237 size = strlenW(wcSrc) + 1;
1239 if(size > numElement)
1241 return MSVCRT_ERANGE;
1244 memcpy( wcDest, wcSrc, size*sizeof(WCHAR) );
1246 return 0;
1249 /******************************************************************
1250 * wcsncpy_s (MSVCRT.@)
1252 INT CDECL MSVCRT_wcsncpy_s( MSVCRT_wchar_t* wcDest, MSVCRT_size_t numElement, const MSVCRT_wchar_t *wcSrc,
1253 MSVCRT_size_t count )
1255 WCHAR *p = wcDest;
1256 BOOL truncate = (count == MSVCRT__TRUNCATE);
1258 if(!wcDest && !numElement && !count)
1259 return 0;
1261 if (!wcDest || !numElement)
1262 return MSVCRT_EINVAL;
1264 if (!wcSrc)
1266 *wcDest = 0;
1267 return count ? MSVCRT_EINVAL : 0;
1270 while (numElement && count && *wcSrc)
1272 *p++ = *wcSrc++;
1273 numElement--;
1274 count--;
1276 if (!numElement && truncate)
1278 *(p-1) = 0;
1279 return MSVCRT_STRUNCATE;
1281 else if (!numElement)
1283 *wcDest = 0;
1284 return MSVCRT_ERANGE;
1287 *p = 0;
1288 return 0;
1291 /******************************************************************
1292 * wcscat_s (MSVCRT.@)
1295 INT CDECL MSVCRT_wcscat_s(MSVCRT_wchar_t* dst, MSVCRT_size_t elem, const MSVCRT_wchar_t* src)
1297 MSVCRT_wchar_t* ptr = dst;
1299 if (!dst || elem == 0) return MSVCRT_EINVAL;
1300 if (!src)
1302 dst[0] = '\0';
1303 return MSVCRT_EINVAL;
1306 /* seek to end of dst string (or elem if no end of string is found */
1307 while (ptr < dst + elem && *ptr != '\0') ptr++;
1308 while (ptr < dst + elem)
1310 if ((*ptr++ = *src++) == '\0') return 0;
1312 /* not enough space */
1313 dst[0] = '\0';
1314 return MSVCRT_ERANGE;
1317 /*********************************************************************
1318 * wcsncat_s (MSVCRT.@)
1321 INT CDECL MSVCRT_wcsncat_s(MSVCRT_wchar_t *dst, MSVCRT_size_t elem,
1322 const MSVCRT_wchar_t *src, MSVCRT_size_t count)
1324 MSVCRT_size_t srclen;
1325 MSVCRT_wchar_t dststart;
1326 INT ret = 0;
1328 if (!MSVCRT_CHECK_PMT(dst != NULL)) return MSVCRT_EINVAL;
1329 if (!MSVCRT_CHECK_PMT(elem > 0)) return MSVCRT_EINVAL;
1330 if (!MSVCRT_CHECK_PMT(src != NULL || count == 0)) return MSVCRT_EINVAL;
1332 if (count == 0)
1333 return 0;
1335 for (dststart = 0; dststart < elem; dststart++)
1337 if (dst[dststart] == '\0')
1338 break;
1340 if (dststart == elem)
1342 MSVCRT_INVALID_PMT("dst[elem] is not NULL terminated\n", MSVCRT_EINVAL);
1343 return MSVCRT_EINVAL;
1346 if (count == MSVCRT__TRUNCATE)
1348 srclen = strlenW(src);
1349 if (srclen >= (elem - dststart))
1351 srclen = elem - dststart - 1;
1352 ret = MSVCRT_STRUNCATE;
1355 else
1356 srclen = min(strlenW(src), count);
1357 if (srclen < (elem - dststart))
1359 memcpy(&dst[dststart], src, srclen*sizeof(MSVCRT_wchar_t));
1360 dst[dststart+srclen] = '\0';
1361 return ret;
1363 MSVCRT_INVALID_PMT("dst[elem] is too small", MSVCRT_ERANGE);
1364 dst[0] = '\0';
1365 return MSVCRT_ERANGE;
1368 /*********************************************************************
1369 * _wcstoi64_l (MSVCRT.@)
1371 * FIXME: locale parameter is ignored
1373 __int64 CDECL MSVCRT__wcstoi64_l(const MSVCRT_wchar_t *nptr,
1374 MSVCRT_wchar_t **endptr, int base, MSVCRT__locale_t locale)
1376 BOOL negative = FALSE;
1377 __int64 ret = 0;
1379 TRACE("(%s %p %d %p)\n", debugstr_w(nptr), endptr, base, locale);
1381 if (!MSVCRT_CHECK_PMT(nptr != NULL)) return 0;
1382 if (!MSVCRT_CHECK_PMT(base == 0 || base >= 2)) return 0;
1383 if (!MSVCRT_CHECK_PMT(base <= 36)) return 0;
1385 while(isspaceW(*nptr)) nptr++;
1387 if(*nptr == '-') {
1388 negative = TRUE;
1389 nptr++;
1390 } else if(*nptr == '+')
1391 nptr++;
1393 if((base==0 || base==16) && *nptr=='0' && tolowerW(*(nptr+1))=='x') {
1394 base = 16;
1395 nptr += 2;
1398 if(base == 0) {
1399 if(*nptr=='0')
1400 base = 8;
1401 else
1402 base = 10;
1405 while(*nptr) {
1406 MSVCRT_wchar_t cur = tolowerW(*nptr);
1407 int v;
1409 if(isdigitW(cur)) {
1410 if(cur >= '0'+base)
1411 break;
1412 v = cur-'0';
1413 } else {
1414 if(cur<'a' || cur>='a'+base-10)
1415 break;
1416 v = cur-'a'+10;
1419 if(negative)
1420 v = -v;
1422 nptr++;
1424 if(!negative && (ret>MSVCRT_I64_MAX/base || ret*base>MSVCRT_I64_MAX-v)) {
1425 ret = MSVCRT_I64_MAX;
1426 *MSVCRT__errno() = MSVCRT_ERANGE;
1427 } else if(negative && (ret<MSVCRT_I64_MIN/base || ret*base<MSVCRT_I64_MIN-v)) {
1428 ret = MSVCRT_I64_MIN;
1429 *MSVCRT__errno() = MSVCRT_ERANGE;
1430 } else
1431 ret = ret*base + v;
1434 if(endptr)
1435 *endptr = (MSVCRT_wchar_t*)nptr;
1437 return ret;
1440 /*********************************************************************
1441 * _wcstoi64 (MSVCRT.@)
1443 __int64 CDECL MSVCRT__wcstoi64(const MSVCRT_wchar_t *nptr,
1444 MSVCRT_wchar_t **endptr, int base)
1446 return MSVCRT__wcstoi64_l(nptr, endptr, base, NULL);
1449 /*********************************************************************
1450 * _wtoi_l (MSVCRT.@)
1452 int __cdecl MSVCRT__wtoi_l(const MSVCRT_wchar_t *str, MSVCRT__locale_t locale)
1454 __int64 ret = MSVCRT__wcstoi64_l(str, NULL, 10, locale);
1456 if(ret > INT_MAX) {
1457 ret = INT_MAX;
1458 *MSVCRT__errno() = MSVCRT_ERANGE;
1459 } else if(ret < INT_MIN) {
1460 ret = INT_MIN;
1461 *MSVCRT__errno() = MSVCRT_ERANGE;
1463 return ret;
1466 /*********************************************************************
1467 * _wtoi (MSVCRT.@)
1469 int __cdecl MSVCRT__wtoi(const MSVCRT_wchar_t *str)
1471 return MSVCRT__wtoi_l(str, NULL);
1474 /*********************************************************************
1475 * _wtol_l (MSVCRT.@)
1477 MSVCRT_long __cdecl MSVCRT__wtol_l(const MSVCRT_wchar_t *str, MSVCRT__locale_t locale)
1479 __int64 ret = MSVCRT__wcstoi64_l(str, NULL, 10, locale);
1481 if(ret > MSVCRT_LONG_MAX) {
1482 ret = MSVCRT_LONG_MAX;
1483 *MSVCRT__errno() = MSVCRT_ERANGE;
1484 } else if(ret < MSVCRT_LONG_MIN) {
1485 ret = MSVCRT_LONG_MIN;
1486 *MSVCRT__errno() = MSVCRT_ERANGE;
1488 return ret;
1491 /*********************************************************************
1492 * _wtol (MSVCRT.@)
1494 MSVCRT_long __cdecl MSVCRT__wtol(const MSVCRT_wchar_t *str)
1496 return MSVCRT__wtol_l(str, NULL);
1499 /*********************************************************************
1500 * _wcstoui64_l (MSVCRT.@)
1502 * FIXME: locale parameter is ignored
1504 unsigned __int64 CDECL MSVCRT__wcstoui64_l(const MSVCRT_wchar_t *nptr,
1505 MSVCRT_wchar_t **endptr, int base, MSVCRT__locale_t locale)
1507 BOOL negative = FALSE;
1508 unsigned __int64 ret = 0;
1510 TRACE("(%s %p %d %p)\n", debugstr_w(nptr), endptr, base, locale);
1512 if (!MSVCRT_CHECK_PMT(nptr != NULL)) return 0;
1513 if (!MSVCRT_CHECK_PMT(base == 0 || base >= 2)) return 0;
1514 if (!MSVCRT_CHECK_PMT(base <= 36)) return 0;
1516 while(isspaceW(*nptr)) nptr++;
1518 if(*nptr == '-') {
1519 negative = TRUE;
1520 nptr++;
1521 } else if(*nptr == '+')
1522 nptr++;
1524 if((base==0 || base==16) && *nptr=='0' && tolowerW(*(nptr+1))=='x') {
1525 base = 16;
1526 nptr += 2;
1529 if(base == 0) {
1530 if(*nptr=='0')
1531 base = 8;
1532 else
1533 base = 10;
1536 while(*nptr) {
1537 MSVCRT_wchar_t cur = tolowerW(*nptr);
1538 int v;
1540 if(isdigitW(cur)) {
1541 if(cur >= '0'+base)
1542 break;
1543 v = *nptr-'0';
1544 } else {
1545 if(cur<'a' || cur>='a'+base-10)
1546 break;
1547 v = cur-'a'+10;
1550 nptr++;
1552 if(ret>MSVCRT_UI64_MAX/base || ret*base>MSVCRT_UI64_MAX-v) {
1553 ret = MSVCRT_UI64_MAX;
1554 *MSVCRT__errno() = MSVCRT_ERANGE;
1555 } else
1556 ret = ret*base + v;
1559 if(endptr)
1560 *endptr = (MSVCRT_wchar_t*)nptr;
1562 return negative ? -ret : ret;
1565 /*********************************************************************
1566 * _wcstoui64 (MSVCRT.@)
1568 unsigned __int64 CDECL MSVCRT__wcstoui64(const MSVCRT_wchar_t *nptr,
1569 MSVCRT_wchar_t **endptr, int base)
1571 return MSVCRT__wcstoui64_l(nptr, endptr, base, NULL);
1574 /******************************************************************
1575 * wcsnlen (MSVCRT.@)
1577 MSVCRT_size_t CDECL MSVCRT_wcsnlen(const MSVCRT_wchar_t *s, MSVCRT_size_t maxlen)
1579 MSVCRT_size_t i;
1581 for (i = 0; i < maxlen; i++)
1582 if (!s[i]) break;
1583 return i;
1586 /*********************************************************************
1587 * _towupper_l (MSVCRT.@)
1589 int CDECL MSVCRT__towupper_l(MSVCRT_wint_t c, MSVCRT__locale_t locale)
1591 return toupperW(c);
1594 /*********************************************************************
1595 * towupper (MSVCRT.@)
1597 int CDECL MSVCRT_towupper(MSVCRT_wint_t c)
1599 return MSVCRT__towupper_l(c, NULL);
1602 /*********************************************************************
1603 * _towlower_l (MSVCRT.@)
1605 int CDECL MSVCRT__towlower_l(MSVCRT_wint_t c, MSVCRT__locale_t locale)
1607 return tolowerW(c);
1610 /*********************************************************************
1611 * towlower (MSVCRT.@)
1613 int CDECL MSVCRT_towlower(MSVCRT_wint_t c)
1615 return MSVCRT__towlower_l(c, NULL);