Use HANDLE instead of HKEY in the NT API.
[wine] / dlls / ntdll / wcstring.c
1 /*
2  * NTDLL wide-char functions
3  *
4  * Copyright 2000 Alexandre Julliard
5  * Copyright 2000 Jon Griffiths
6  * Copyright 2003 Thomas Mertes
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include "config.h"
24
25 #include <ctype.h>
26 #include <limits.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31
32 #include "windef.h"
33 #include "winbase.h"
34 #include "winternl.h"
35 #include "wine/unicode.h"
36 #include "wine/debug.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
39
40
41 /*********************************************************************
42  *           _wcsicmp    (NTDLL.@)
43  */
44 INT __cdecl NTDLL__wcsicmp( LPCWSTR str1, LPCWSTR str2 )
45 {
46     return strcmpiW( str1, str2 );
47 }
48
49
50 /*********************************************************************
51  *           _wcslwr    (NTDLL.@)
52  */
53 LPWSTR __cdecl NTDLL__wcslwr( LPWSTR str )
54 {
55     return strlwrW( str );
56 }
57
58
59 /*********************************************************************
60  *           _wcsnicmp    (NTDLL.@)
61  */
62 INT __cdecl NTDLL__wcsnicmp( LPCWSTR str1, LPCWSTR str2, INT n )
63 {
64     return strncmpiW( str1, str2, n );
65 }
66
67
68 /*********************************************************************
69  *           _wcsupr    (NTDLL.@)
70  */
71 LPWSTR __cdecl NTDLL__wcsupr( LPWSTR str )
72 {
73     return struprW( str );
74 }
75
76
77 /*********************************************************************
78  *           towlower    (NTDLL.@)
79  */
80 WCHAR __cdecl NTDLL_towlower( WCHAR ch )
81 {
82     return tolowerW(ch);
83 }
84
85
86 /*********************************************************************
87  *           towupper    (NTDLL.@)
88  */
89 WCHAR __cdecl NTDLL_towupper( WCHAR ch )
90 {
91     return toupperW(ch);
92 }
93
94
95 /***********************************************************************
96  *           wcscat    (NTDLL.@)
97  */
98 LPWSTR __cdecl NTDLL_wcscat( LPWSTR dst, LPCWSTR src )
99 {
100     return strcatW( dst, src );
101 }
102
103
104 /*********************************************************************
105  *           wcschr    (NTDLL.@)
106  */
107 LPWSTR __cdecl NTDLL_wcschr( LPCWSTR str, WCHAR ch )
108 {
109     return strchrW( str, ch );
110 }
111
112
113 /*********************************************************************
114  *           wcscmp    (NTDLL.@)
115  */
116 INT __cdecl NTDLL_wcscmp( LPCWSTR str1, LPCWSTR str2 )
117 {
118     return strcmpW( str1, str2 );
119 }
120
121
122 /***********************************************************************
123  *           wcscpy    (NTDLL.@)
124  */
125 LPWSTR __cdecl NTDLL_wcscpy( LPWSTR dst, LPCWSTR src )
126 {
127     return strcpyW( dst, src );
128 }
129
130
131 /*********************************************************************
132  *           wcscspn    (NTDLL.@)
133  */
134 INT __cdecl NTDLL_wcscspn( LPCWSTR str, LPCWSTR reject )
135 {
136     LPCWSTR start = str;
137     while (*str)
138     {
139         LPCWSTR p = reject;
140         while (*p && (*p != *str)) p++;
141         if (*p) break;
142         str++;
143     }
144     return str - start;
145 }
146
147
148 /***********************************************************************
149  *           wcslen    (NTDLL.@)
150  */
151 INT __cdecl NTDLL_wcslen( LPCWSTR str )
152 {
153     return strlenW( str );
154 }
155
156
157 /*********************************************************************
158  *           wcsncat    (NTDLL.@)
159  */
160 LPWSTR __cdecl NTDLL_wcsncat( LPWSTR s1, LPCWSTR s2, INT n )
161 {
162     LPWSTR ret = s1;
163     while (*s1) s1++;
164     while (n-- > 0) if (!(*s1++ = *s2++)) return ret;
165     *s1 = 0;
166     return ret;
167 }
168
169
170 /*********************************************************************
171  *           wcsncmp    (NTDLL.@)
172  */
173 INT __cdecl NTDLL_wcsncmp( LPCWSTR str1, LPCWSTR str2, INT n )
174 {
175     return strncmpW( str1, str2, n );
176 }
177
178
179 /*********************************************************************
180  *           wcsncpy    (NTDLL.@)
181  */
182 LPWSTR __cdecl NTDLL_wcsncpy( LPWSTR s1, LPCWSTR s2, INT n )
183 {
184     WCHAR *ret = s1;
185     while (n-- > 0) if (!(*s1++ = *s2++)) break;
186     while (n-- > 0) *s1++ = 0;
187     return ret;
188 }
189
190
191 /*********************************************************************
192  *           wcspbrk    (NTDLL.@)
193  */
194 LPWSTR __cdecl NTDLL_wcspbrk( LPCWSTR str, LPCWSTR accept )
195 {
196     LPCWSTR p;
197     while (*str)
198     {
199         for (p = accept; *p; p++) if (*p == *str) return (LPWSTR)str;
200         str++;
201     }
202     return NULL;
203 }
204
205
206 /*********************************************************************
207  *           wcsrchr    (NTDLL.@)
208  */
209 LPWSTR __cdecl NTDLL_wcsrchr( LPWSTR str, WCHAR ch )
210 {
211     LPWSTR last = NULL;
212     while (*str)
213     {
214         if (*str == ch) last = str;
215         str++;
216     }
217     return last;
218 }
219
220
221 /*********************************************************************
222  *           wcsspn    (NTDLL.@)
223  */
224 INT __cdecl NTDLL_wcsspn( LPCWSTR str, LPCWSTR accept )
225 {
226     LPCWSTR start = str;
227     while (*str)
228     {
229         LPCWSTR p = accept;
230         while (*p && (*p != *str)) p++;
231         if (!*p) break;
232         str++;
233     }
234     return str - start;
235 }
236
237
238 /*********************************************************************
239  *           wcsstr    (NTDLL.@)
240  */
241 LPWSTR __cdecl NTDLL_wcsstr( LPCWSTR str, LPCWSTR sub )
242 {
243     return strstrW( str, sub );
244 }
245
246
247 /*********************************************************************
248  *           wcstok    (NTDLL.@)
249  */
250 LPWSTR __cdecl NTDLL_wcstok( LPWSTR str, LPCWSTR delim )
251 {
252     static LPWSTR next = NULL;
253     LPWSTR ret;
254
255     if (!str)
256         if (!(str = next)) return NULL;
257
258     while (*str && NTDLL_wcschr( delim, *str )) str++;
259     if (!*str) return NULL;
260     ret = str++;
261     while (*str && !NTDLL_wcschr( delim, *str )) str++;
262     if (*str) *str++ = 0;
263     next = str;
264     return ret;
265 }
266
267
268 /*********************************************************************
269  *           wcstombs    (NTDLL.@)
270  */
271 INT __cdecl NTDLL_wcstombs( LPSTR dst, LPCWSTR src, INT n )
272 {
273     DWORD len;
274
275     if (!dst)
276     {
277         RtlUnicodeToMultiByteSize( &len, src, strlenW(src)*sizeof(WCHAR) );
278         return len;
279     }
280     else
281     {
282         if (n <= 0) return 0;
283         RtlUnicodeToMultiByteN( dst, n, &len, src, strlenW(src)*sizeof(WCHAR) );
284         if (len < n) dst[len] = 0;
285     }
286     return len;
287 }
288
289
290 /*********************************************************************
291  *           mbstowcs    (NTDLL.@)
292  */
293 INT __cdecl NTDLL_mbstowcs( LPWSTR dst, LPCSTR src, INT n )
294 {
295     DWORD len;
296
297     if (!dst)
298     {
299         RtlMultiByteToUnicodeSize( &len, src, strlen(src) );
300     }
301     else
302     {
303         if (n <= 0) return 0;
304         RtlMultiByteToUnicodeN( dst, n*sizeof(WCHAR), &len, src, strlen(src) );
305         if (len / sizeof(WCHAR) < n) dst[len / sizeof(WCHAR)] = 0;
306     }
307     return len / sizeof(WCHAR);
308 }
309
310
311 /*********************************************************************
312  *                  wcstol  (NTDLL.@)
313  */
314 long __cdecl NTDLL_wcstol(LPCWSTR s,LPWSTR *end,INT base)
315 {
316     return strtolW( s, end, base );
317 }
318
319
320 /*********************************************************************
321  *                  wcstoul  (NTDLL.@)
322  */
323 unsigned long __cdecl NTDLL_wcstoul(LPCWSTR s,LPWSTR *end,INT base)
324 {
325     return strtoulW( s, end, base );
326 }
327
328
329 /*********************************************************************
330  *           iswctype    (NTDLL.@)
331  */
332 INT __cdecl NTDLL_iswctype( WCHAR wc, WCHAR wct )
333 {
334     return (get_char_typeW(wc) & 0xfff) & wct;
335 }
336
337
338 /*********************************************************************
339  *           iswalpha    (NTDLL.@)
340  *
341  * Checks if an unicode char wc is a letter
342  *
343  * RETURNS
344  *  TRUE: The unicode char wc is a letter.
345  *  FALSE: Otherwise
346  */
347 INT __cdecl NTDLL_iswalpha( WCHAR wc )
348 {
349     return isalphaW(wc);
350 }
351
352
353 /*********************************************************************
354  *              iswdigit (NTDLL.@)
355  *
356  * Checks if an unicode char wc is a digit
357  *
358  * RETURNS
359  *  TRUE: The unicode char wc is a digit.
360  *  FALSE: Otherwise
361  */
362 INT __cdecl NTDLL_iswdigit( WCHAR wc )
363 {
364     return isdigitW(wc);
365 }
366
367
368 /*********************************************************************
369  *              iswlower (NTDLL.@)
370  *
371  * Checks if an unicode char wc is a lower case letter
372  *
373  * RETURNS
374  *  TRUE: The unicode char wc is a lower case letter.
375  *  FALSE: Otherwise
376  */
377 INT __cdecl NTDLL_iswlower( WCHAR wc )
378 {
379     return islowerW(wc);
380 }
381
382
383 /*********************************************************************
384  *              iswspace (NTDLL.@)
385  *
386  * Checks if an unicode char wc is a white space character
387  *
388  * RETURNS
389  *  TRUE: The unicode char wc is a white space character.
390  *  FALSE: Otherwise
391  */
392 INT __cdecl NTDLL_iswspace( WCHAR wc )
393 {
394     return isspaceW(wc);
395 }
396
397
398 /*********************************************************************
399  *              iswxdigit (NTDLL.@)
400  *
401  * Checks if an unicode char wc is an extended digit
402  *
403  * RETURNS
404  *  TRUE: The unicode char wc is an extended digit.
405  *  FALSE: Otherwise
406  */
407 INT __cdecl NTDLL_iswxdigit( WCHAR wc )
408 {
409     return isxdigitW(wc);
410 }
411
412
413 /*********************************************************************
414  *      _ultow   (NTDLL.@)
415  *
416  * Converts an unsigned long integer to an unicode string.
417  *
418  * RETURNS
419  *  Always returns str.
420  *
421  * NOTES
422  *  Converts value to a '\0' terminated wstring which is copied to str.
423  *  The maximum length of the copied str is 33 bytes.
424  *  Does not check if radix is in the range of 2 to 36.
425  *  If str is NULL it just returns NULL.
426  */
427 LPWSTR __cdecl _ultow(
428     unsigned long value, /* [I] Value to be converted */
429     LPWSTR str,          /* [O] Destination for the converted value */
430     INT radix)           /* [I] Number base for conversion */
431 {
432     WCHAR buffer[33];
433     PWCHAR pos;
434     WCHAR digit;
435
436     pos = &buffer[32];
437     *pos = '\0';
438
439     do {
440         digit = value % radix;
441         value = value / radix;
442         if (digit < 10) {
443             *--pos = '0' + digit;
444         } else {
445             *--pos = 'a' + digit - 10;
446         } /* if */
447     } while (value != 0L);
448
449     if (str != NULL) {
450         memcpy(str, pos, (&buffer[32] - pos + 1) * sizeof(WCHAR));
451     } /* if */
452     return str;
453 }
454
455
456 /*********************************************************************
457  *      _ltow   (NTDLL.@)
458  *
459  * Converts a long integer to an unicode string.
460  *
461  * RETURNS
462  *  Always returns str.
463  *
464  * NOTES
465  *  Converts value to a '\0' terminated wstring which is copied to str.
466  *  The maximum length of the copied str is 33 bytes. If radix
467  *  is 10 and value is negative, the value is converted with sign.
468  *  Does not check if radix is in the range of 2 to 36.
469  *  If str is NULL it just returns NULL.
470  */
471 LPWSTR __cdecl _ltow(
472     long value, /* [I] Value to be converted */
473     LPWSTR str, /* [O] Destination for the converted value */
474     INT radix)  /* [I] Number base for conversion */
475 {
476     unsigned long val;
477     int negative;
478     WCHAR buffer[33];
479     PWCHAR pos;
480     WCHAR digit;
481
482     if (value < 0 && radix == 10) {
483         negative = 1;
484         val = -value;
485     } else {
486         negative = 0;
487         val = value;
488     } /* if */
489
490     pos = &buffer[32];
491     *pos = '\0';
492
493     do {
494         digit = val % radix;
495         val = val / radix;
496         if (digit < 10) {
497             *--pos = '0' + digit;
498         } else {
499             *--pos = 'a' + digit - 10;
500         } /* if */
501     } while (val != 0L);
502
503     if (negative) {
504         *--pos = '-';
505     } /* if */
506
507     if (str != NULL) {
508         memcpy(str, pos, (&buffer[32] - pos + 1) * sizeof(WCHAR));
509     } /* if */
510     return str;
511 }
512
513
514 /*********************************************************************
515  *      _itow    (NTDLL.@)
516  *
517  * Converts an integer to an unicode string.
518  *
519  * RETURNS
520  *  Always returns str.
521  *
522  * NOTES
523  *  Converts value to a '\0' terminated wstring which is copied to str.
524  *  The maximum length of the copied str is 33 bytes. If radix
525  *  is 10 and value is negative, the value is converted with sign.
526  *  Does not check if radix is in the range of 2 to 36.
527  *  If str is NULL it just returns NULL.
528  *
529  * DIFFERENCES
530  * - The native function crashes when the string is longer than 19 chars.
531  *   This function does not have this bug.
532  */
533 LPWSTR __cdecl _itow(
534     int value,  /* [I] Value to be converted */
535     LPWSTR str, /* [O] Destination for the converted value */
536     INT radix)  /* [I] Number base for conversion */
537 {
538     return _ltow(value, str, radix);
539 }
540
541
542 /*********************************************************************
543  *      _ui64tow   (NTDLL.@)
544  *
545  * Converts a large unsigned integer to an unicode string.
546  *
547  * RETURNS
548  *  Always returns str.
549  *
550  * NOTES
551  *  Converts value to a '\0' terminated wstring which is copied to str.
552  *  The maximum length of the copied str is 33 bytes.
553  *  Does not check if radix is in the range of 2 to 36.
554  *  If str is NULL it just returns NULL.
555  *
556  * DIFFERENCES
557  * - This function does not exist in the native DLL (but in msvcrt).
558  *   But since the maintenance of all these functions is better done
559  *   in one place we implement it here.
560  */
561 LPWSTR __cdecl _ui64tow(
562     ULONGLONG value, /* [I] Value to be converted */
563     LPWSTR str,      /* [O] Destination for the converted value */
564     INT radix)       /* [I] Number base for conversion */
565 {
566     WCHAR buffer[65];
567     PWCHAR pos;
568     WCHAR digit;
569
570     pos = &buffer[64];
571     *pos = '\0';
572
573     do {
574         digit = value % radix;
575         value = value / radix;
576         if (digit < 10) {
577             *--pos = '0' + digit;
578         } else {
579             *--pos = 'a' + digit - 10;
580         } /* if */
581     } while (value != 0L);
582
583     if (str != NULL) {
584         memcpy(str, pos, (&buffer[64] - pos + 1) * sizeof(WCHAR));
585     } /* if */
586     return str;
587 }
588
589
590 /*********************************************************************
591  *      _i64tow   (NTDLL.@)
592  *
593  * Converts a large integer to an unicode string.
594  *
595  * RETURNS
596  *  Always returns str.
597  *
598  * NOTES
599  *  Converts value to a '\0' terminated wstring which is copied to str.
600  *  The maximum length of the copied str is 33 bytes. If radix
601  *  is 10 and value is negative, the value is converted with sign.
602  *  Does not check if radix is in the range of 2 to 36.
603  *  If str is NULL it just returns NULL.
604  *
605  * DIFFERENCES
606  * - The native DLL converts negative values (for base 10) wrong:
607  *                     -1 is converted to -18446744073709551615
608  *                     -2 is converted to -18446744073709551614
609  *   -9223372036854775807 is converted to  -9223372036854775809
610  *   -9223372036854775808 is converted to  -9223372036854775808
611  *   The native msvcrt _i64tow function and our ntdll function do
612  *   not have this bug.
613  */
614 LPWSTR __cdecl _i64tow(
615     LONGLONG value, /* [I] Value to be converted */
616     LPWSTR str,     /* [O] Destination for the converted value */
617     INT radix)      /* [I] Number base for conversion */
618 {
619     ULONGLONG val;
620     int negative;
621     WCHAR buffer[65];
622     PWCHAR pos;
623     WCHAR digit;
624
625     if (value < 0 && radix == 10) {
626         negative = 1;
627         val = -value;
628     } else {
629         negative = 0;
630         val = value;
631     } /* if */
632
633     pos = &buffer[64];
634     *pos = '\0';
635
636     do {
637         digit = val % radix;
638         val = val / radix;
639         if (digit < 10) {
640             *--pos = '0' + digit;
641         } else {
642             *--pos = 'a' + digit - 10;
643         } /* if */
644     } while (val != 0L);
645
646     if (negative) {
647         *--pos = '-';
648     } /* if */
649
650     if (str != NULL) {
651         memcpy(str, pos, (&buffer[64] - pos + 1) * sizeof(WCHAR));
652     } /* if */
653     return str;
654 }
655
656
657 /*********************************************************************
658  *      _wtol    (NTDLL.@)
659  *
660  * Converts an unicode string to a long integer.
661  *
662  * PARAMS
663  *  str [I] Wstring to be converted
664  *
665  * RETURNS
666  *  On success it returns the integer value otherwise it returns 0.
667  *
668  * NOTES
669  *  Accepts: {whitespace} [+|-] {digits}
670  *  No check is made for value overflow, only the lower 32 bits are assigned.
671  *  If str is NULL it crashes, as the native function does.
672  */
673 LONG __cdecl _wtol( LPCWSTR str )
674 {
675     ULONG RunningTotal = 0;
676     char bMinus = 0;
677
678     while (isspaceW(*str)) {
679         str++;
680     } /* while */
681
682     if (*str == '+') {
683         str++;
684     } else if (*str == '-') {
685         bMinus = 1;
686         str++;
687     } /* if */
688
689     while (*str >= '0' && *str <= '9') {
690         RunningTotal = RunningTotal * 10 + *str - '0';
691         str++;
692     } /* while */
693
694     return bMinus ? -RunningTotal : RunningTotal;
695 }
696
697
698 /*********************************************************************
699  *      _wtoi    (NTDLL.@)
700  *
701  * Converts an unicode string to an integer.
702  *
703  * PARAMS
704  *  str [I] Wstring to be converted
705  *
706  * RETURNS
707  *  On success it returns the integer value otherwise it returns 0.
708  *
709  * NOTES
710  *  Accepts: {whitespace} [+|-] {digits}
711  *  No check is made for value overflow, only the lower 32 bits are assigned.
712  *  If str is NULL it crashes, as the native function does.
713  */
714 int __cdecl _wtoi( LPCWSTR str )
715 {
716     return _wtol(str);
717 }
718
719
720 /*********************************************************************
721  *      _wtoi64   (NTDLL.@)
722  *
723  * Converts an unicode string to a large integer.
724  *
725  * PARAMS
726  *  str [I] Wstring to be converted
727  *
728  * RETURNS
729  *  On success it returns the integer value otherwise it returns 0.
730  *
731  * NOTES
732  *  Accepts: {whitespace} [+|-] {digits}
733  *  No check is made for value overflow, only the lower 64 bits are assigned.
734  *  If str is NULL it crashes, as the native function does.
735  */
736 LONGLONG  __cdecl _wtoi64( LPCWSTR str )
737 {
738     ULONGLONG RunningTotal = 0;
739     char bMinus = 0;
740
741     while (isspaceW(*str)) {
742         str++;
743     } /* while */
744
745     if (*str == '+') {
746         str++;
747     } else if (*str == '-') {
748         bMinus = 1;
749         str++;
750     } /* if */
751
752     while (*str >= '0' && *str <= '9') {
753         RunningTotal = RunningTotal * 10 + *str - '0';
754         str++;
755     } /* while */
756
757     return bMinus ? -RunningTotal : RunningTotal;
758 }
759
760
761 /***********************************************************************
762  *        _snwprintf (NTDLL.@)
763  */
764 int __cdecl _snwprintf(WCHAR *str, unsigned int len, const WCHAR *format, ...)
765 {
766   int retval;
767   va_list valist;
768   va_start(valist, format);
769   retval = vsnprintfW(str, len, format, valist);
770   va_end(valist);
771   return retval;
772 }
773
774
775 /***********************************************************************
776  *        swprintf (NTDLL.@)
777  */
778 int __cdecl NTDLL_swprintf(WCHAR *str, const WCHAR *format, ...)
779 {
780   int retval;
781   va_list valist;
782   va_start(valist, format);
783   retval = vsnprintfW(str, INT_MAX, format, valist);
784   va_end(valist);
785   return retval;
786 }