msi: Implement Installer::OpenDatabase.
[wine] / dlls / ntdll / string.c
1 /*
2  * NTDLL string 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <ctype.h>
27 #include <stdarg.h>
28 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <search.h>
32
33 #include "windef.h"
34 #include "winternl.h"
35
36
37 /*********************************************************************
38  *                  memchr   (NTDLL.@)
39  */
40 void * __cdecl NTDLL_memchr( const void *ptr, int c, size_t n )
41 {
42     return memchr( ptr, c, n );
43 }
44
45
46 /*********************************************************************
47  *                  memcmp   (NTDLL.@)
48  */
49 int __cdecl NTDLL_memcmp( const void *ptr1, const void *ptr2, size_t n )
50 {
51     return memcmp( ptr1, ptr2, n );
52 }
53
54
55 /*********************************************************************
56  *                  memcpy   (NTDLL.@)
57  *
58  * NOTES
59  *  Behaves like memmove.
60  */
61 void * __cdecl NTDLL_memcpy( void *dst, const void *src, size_t n )
62 {
63     return memmove( dst, src, n );
64 }
65
66
67 /*********************************************************************
68  *                  memmove   (NTDLL.@)
69  */
70 void * __cdecl NTDLL_memmove( void *dst, const void *src, size_t n )
71 {
72     return memmove( dst, src, n );
73 }
74
75
76 /*********************************************************************
77  *                  memset   (NTDLL.@)
78  */
79 void * __cdecl NTDLL_memset( void *dst, int c, size_t n )
80 {
81     return memset( dst, c, n );
82 }
83
84
85 /*********************************************************************
86  *                  bsearch   (NTDLL.@)
87  */
88 void * __cdecl NTDLL_bsearch( const void *key, const void *base, size_t nmemb,
89                               size_t size, int (*compar)(const void *, const void *) )
90 {
91     return bsearch( key, base, nmemb, size, compar );
92 }
93
94
95 /*********************************************************************
96  *                  qsort   (NTDLL.@)
97  */
98 void __cdecl NTDLL_qsort( void *base, size_t nmemb, size_t size,
99                           int(*compar)(const void *, const void *) )
100 {
101     qsort( base, nmemb, size, compar );
102 }
103
104
105 /*********************************************************************
106  *                  _lfind   (NTDLL.@)
107  */
108 void * __cdecl _lfind( const void *key, const void *base, unsigned int *nmemb,
109                        size_t size, int(*compar)(const void *, const void *) )
110 {
111     size_t n = *nmemb;
112     return lfind( key, base, &n, size, compar );
113 }
114
115
116 /*********************************************************************
117  *                  strcat   (NTDLL.@)
118  */
119 char * __cdecl NTDLL_strcat( char *dst, const char *src )
120 {
121     return strcat( dst, src );
122 }
123
124
125 /*********************************************************************
126  *                  strchr   (NTDLL.@)
127  */
128 char * __cdecl NTDLL_strchr( const char *str, int c )
129 {
130     return strchr( str, c );
131 }
132
133
134 /*********************************************************************
135  *                  strcmp   (NTDLL.@)
136  */
137 int __cdecl NTDLL_strcmp( const char *str1, const char *str2 )
138 {
139     return strcmp( str1, str2 );
140 }
141
142
143 /*********************************************************************
144  *                  strcpy   (NTDLL.@)
145  */
146 char * __cdecl NTDLL_strcpy( char *dst, const char *src )
147 {
148     return strcpy( dst, src );
149 }
150
151
152 /*********************************************************************
153  *                  strcspn   (NTDLL.@)
154  */
155 size_t __cdecl NTDLL_strcspn( const char *str, const char *reject )
156 {
157     return strcspn( str, reject );
158 }
159
160
161 /*********************************************************************
162  *                  strlen   (NTDLL.@)
163  */
164 size_t __cdecl NTDLL_strlen( const char *str )
165 {
166     return strlen( str );
167 }
168
169
170 /*********************************************************************
171  *                  strncat   (NTDLL.@)
172  */
173 char * __cdecl NTDLL_strncat( char *dst, const char *src, size_t len )
174 {
175     return strncat( dst, src, len );
176 }
177
178
179 /*********************************************************************
180  *                  strncmp   (NTDLL.@)
181  */
182 int __cdecl NTDLL_strncmp( const char *str1, const char *str2, size_t len )
183 {
184     return strncmp( str1, str2, len );
185 }
186
187
188 /*********************************************************************
189  *                  strncpy   (NTDLL.@)
190  */
191 char * __cdecl NTDLL_strncpy( char *dst, const char *src, size_t len )
192 {
193     return strncpy( dst, src, len );
194 }
195
196
197 /*********************************************************************
198  *                  strpbrk   (NTDLL.@)
199  */
200 char * __cdecl NTDLL_strpbrk( const char *str, const char *accept )
201 {
202     return strpbrk( str, accept );
203 }
204
205
206 /*********************************************************************
207  *                  strrchr   (NTDLL.@)
208  */
209 char * __cdecl NTDLL_strrchr( const char *str, int c )
210 {
211     return strrchr( str, c );
212 }
213
214
215 /*********************************************************************
216  *                  strspn   (NTDLL.@)
217  */
218 size_t __cdecl NTDLL_strspn( const char *str, const char *accept )
219 {
220     return strspn( str, accept );
221 }
222
223
224 /*********************************************************************
225  *                  strstr   (NTDLL.@)
226  */
227 char * __cdecl NTDLL_strstr( const char *haystack, const char *needle )
228 {
229     return strstr( haystack, needle );
230 }
231
232
233 /*********************************************************************
234  *                  _memccpy   (NTDLL.@)
235  */
236 void * __cdecl _memccpy( void *dst, const void *src, int c, size_t n )
237 {
238     return memccpy( dst, src, c, n );
239 }
240
241
242 /*********************************************************************
243  *                  _memicmp   (NTDLL.@)
244  *
245  * Compare two blocks of memory as strings, ignoring case.
246  *
247  * PARAMS
248  *  s1  [I] First string to compare to s2
249  *  s2  [I] Second string to compare to s1
250  *  len [I] Number of bytes to compare
251  *
252  * RETURNS
253  *  An integer less than, equal to, or greater than zero indicating that
254  *  s1 is less than, equal to or greater than s2 respectively.
255  *
256  * NOTES
257  *  Any Nul characters in s1 or s2 are ignored. This function always
258  *  compares up to len bytes or the first place where s1 and s2 differ.
259  */
260 INT __cdecl _memicmp( LPCSTR s1, LPCSTR s2, DWORD len )
261 {
262     int ret = 0;
263     while (len--)
264     {
265         if ((ret = tolower(*s1) - tolower(*s2))) break;
266         s1++;
267         s2++;
268     }
269     return ret;
270 }
271
272
273 /*********************************************************************
274  *                  _stricmp   (NTDLL.@)
275  *                  _strcmpi   (NTDLL.@)
276  */
277 int __cdecl _stricmp( LPCSTR str1, LPCSTR str2 )
278 {
279     return strcasecmp( str1, str2 );
280 }
281
282
283 /*********************************************************************
284  *                  _strnicmp   (NTDLL.@)
285  */
286 int __cdecl _strnicmp( LPCSTR str1, LPCSTR str2, size_t n )
287 {
288     return strncasecmp( str1, str2, n );
289 }
290
291
292 /*********************************************************************
293  *                  _strupr   (NTDLL.@)
294  *
295  * Convert a string to upper case.
296  *
297  * PARAMS
298  *  str [I/O] String to convert
299  *
300  * RETURNS
301  *  str. There is no error return, if str is NULL or invalid, this
302  *  function will crash.
303  */
304 LPSTR __cdecl _strupr( LPSTR str )
305 {
306     LPSTR ret = str;
307     for ( ; *str; str++) *str = toupper(*str);
308     return ret;
309 }
310
311
312 /*********************************************************************
313  *                  _strlwr   (NTDLL.@)
314  *
315  * Convert a string to lowercase
316  *
317  * PARAMS
318  *  str [I/O] String to convert
319  *
320  * RETURNS
321  *  str. There is no error return, if str is NULL or invalid, this
322  *  function will crash.
323  */
324 LPSTR __cdecl _strlwr( LPSTR str )
325 {
326     LPSTR ret = str;
327     for ( ; *str; str++) *str = tolower(*str);
328     return ret;
329 }
330
331
332 /*********************************************************************
333  *                  tolower   (NTDLL.@)
334  */
335 int __cdecl NTDLL_tolower( int c )
336 {
337     return tolower( c );
338 }
339
340
341 /*********************************************************************
342  *                  toupper   (NTDLL.@)
343  */
344 int __cdecl NTDLL_toupper( int c )
345 {
346     return toupper( c );
347 }
348
349
350 /*********************************************************************
351  *                  isalnum   (NTDLL.@)
352  */
353 int __cdecl NTDLL_isalnum( int c )
354 {
355     return isalnum( c );
356 }
357
358
359 /*********************************************************************
360  *                  isalpha   (NTDLL.@)
361  */
362 int __cdecl NTDLL_isalpha( int c )
363 {
364     return isalpha( c );
365 }
366
367
368 /*********************************************************************
369  *                  iscntrl   (NTDLL.@)
370  */
371 int __cdecl NTDLL_iscntrl( int c )
372 {
373     return iscntrl( c );
374 }
375
376
377 /*********************************************************************
378  *                  isdigit   (NTDLL.@)
379  */
380 int __cdecl NTDLL_isdigit( int c )
381 {
382     return isdigit( c );
383 }
384
385
386 /*********************************************************************
387  *                  isgraph   (NTDLL.@)
388  */
389 int __cdecl NTDLL_isgraph( int c )
390 {
391     return isgraph( c );
392 }
393
394
395 /*********************************************************************
396  *                  islower   (NTDLL.@)
397  */
398 int __cdecl NTDLL_islower( int c )
399 {
400     return islower( c );
401 }
402
403
404 /*********************************************************************
405  *                  isprint   (NTDLL.@)
406  */
407 int __cdecl NTDLL_isprint( int c )
408 {
409     return isprint( c );
410 }
411
412
413 /*********************************************************************
414  *                  ispunct   (NTDLL.@)
415  */
416 int __cdecl NTDLL_ispunct( int c )
417 {
418     return ispunct( c );
419 }
420
421
422 /*********************************************************************
423  *                  isspace   (NTDLL.@)
424  */
425 int __cdecl NTDLL_isspace( int c )
426 {
427     return isspace( c );
428 }
429
430
431 /*********************************************************************
432  *                  isupper   (NTDLL.@)
433  */
434 int __cdecl NTDLL_isupper( int c )
435 {
436     return isupper( c );
437 }
438
439
440 /*********************************************************************
441  *                  isxdigit   (NTDLL.@)
442  */
443 int __cdecl NTDLL_isxdigit( int c )
444 {
445     return isxdigit( c );
446 }
447
448
449 /*********************************************************************
450  *                  strtol   (NTDLL.@)
451  */
452 long __cdecl NTDLL_strtol( const char *nptr, char **endptr, int base )
453 {
454     return strtol( nptr, endptr, base );
455 }
456
457
458 /*********************************************************************
459  *                  strtoul   (NTDLL.@)
460  */
461 unsigned long __cdecl NTDLL_strtoul( const char *nptr, char **endptr, int base )
462 {
463     return strtoul( nptr, endptr, base );
464 }
465
466
467 /*********************************************************************
468  *                  atoi   (NTDLL.@)
469  */
470 int __cdecl NTDLL_atoi( const char *nptr )
471 {
472     return atoi( nptr );
473 }
474
475
476 /*********************************************************************
477  *                  atol   (NTDLL.@)
478  */
479 long __cdecl NTDLL_atol( const char *nptr )
480 {
481     return atol( nptr );
482 }
483
484
485 /*********************************************************************
486  *      _ultoa   (NTDLL.@)
487  *
488  * Convert an unsigned long integer to a string.
489  *
490  * RETURNS
491  *  str.
492  *
493  * NOTES
494  *  - Converts value to a Nul terminated string which is copied to str.
495  *  - The maximum length of the copied str is 33 bytes.
496  *  - Does not check if radix is in the range of 2 to 36.
497  *  - If str is NULL it crashes, as the native function does.
498  */
499 char * __cdecl _ultoa(
500     unsigned long value, /* [I] Value to be converted */
501     char *str,           /* [O] Destination for the converted value */
502     int radix)           /* [I] Number base for conversion */
503 {
504     char buffer[33];
505     char *pos;
506     int digit;
507
508     pos = &buffer[32];
509     *pos = '\0';
510
511     do {
512         digit = value % radix;
513         value = value / radix;
514         if (digit < 10) {
515             *--pos = '0' + digit;
516         } else {
517             *--pos = 'a' + digit - 10;
518         } /* if */
519     } while (value != 0L);
520
521     memcpy(str, pos, &buffer[32] - pos + 1);
522     return str;
523 }
524
525
526 /*********************************************************************
527  *      _ltoa   (NTDLL.@)
528  *
529  * Convert a long integer to a string.
530  *
531  * RETURNS
532  *  str.
533  *
534  * NOTES
535  *  - Converts value to a Nul terminated string which is copied to str.
536  *  - The maximum length of the copied str is 33 bytes. If radix
537  *  is 10 and value is negative, the value is converted with sign.
538  *  - Does not check if radix is in the range of 2 to 36.
539  *  - If str is NULL it crashes, as the native function does.
540  */
541 char * __cdecl _ltoa(
542     long value, /* [I] Value to be converted */
543     char *str,  /* [O] Destination for the converted value */
544     int radix)  /* [I] Number base for conversion */
545 {
546     unsigned long val;
547     int negative;
548     char buffer[33];
549     char *pos;
550     int digit;
551
552     if (value < 0 && radix == 10) {
553         negative = 1;
554         val = -value;
555     } else {
556         negative = 0;
557         val = value;
558     } /* if */
559
560     pos = &buffer[32];
561     *pos = '\0';
562
563     do {
564         digit = val % radix;
565         val = val / radix;
566         if (digit < 10) {
567             *--pos = '0' + digit;
568         } else {
569             *--pos = 'a' + digit - 10;
570         } /* if */
571     } while (val != 0L);
572
573     if (negative) {
574         *--pos = '-';
575     } /* if */
576
577     memcpy(str, pos, &buffer[32] - pos + 1);
578     return str;
579 }
580
581
582 /*********************************************************************
583  *      _itoa    (NTDLL.@)
584  *
585  * Converts an integer to a string.
586  *
587  * RETURNS
588  *  str.
589  *
590  * NOTES
591  *  - Converts value to a '\0' terminated string which is copied to str.
592  *  - The maximum length of the copied str is 33 bytes. If radix
593  *  is 10 and value is negative, the value is converted with sign.
594  *  - Does not check if radix is in the range of 2 to 36.
595  *  - If str is NULL it crashes, as the native function does.
596  */
597 char * __cdecl _itoa(
598     int value, /* [I] Value to be converted */
599     char *str, /* [O] Destination for the converted value */
600     int radix) /* [I] Number base for conversion */
601 {
602     return _ltoa(value, str, radix);
603 }
604
605
606 /*********************************************************************
607  *      _ui64toa   (NTDLL.@)
608  *
609  * Converts a large unsigned integer to a string.
610  *
611  * RETURNS
612  *  str.
613  *
614  * NOTES
615  *  - Converts value to a '\0' terminated string which is copied to str.
616  *  - The maximum length of the copied str is 65 bytes.
617  *  - Does not check if radix is in the range of 2 to 36.
618  *  - If str is NULL it crashes, as the native function does.
619  */
620 char * __cdecl _ui64toa(
621     ULONGLONG value, /* [I] Value to be converted */
622     char *str,       /* [O] Destination for the converted value */
623     int radix)       /* [I] Number base for conversion */
624 {
625     char buffer[65];
626     char *pos;
627     int digit;
628
629     pos = &buffer[64];
630     *pos = '\0';
631
632     do {
633         digit = value % radix;
634         value = value / radix;
635         if (digit < 10) {
636             *--pos = '0' + digit;
637         } else {
638             *--pos = 'a' + digit - 10;
639         } /* if */
640     } while (value != 0L);
641
642     memcpy(str, pos, &buffer[64] - pos + 1);
643     return str;
644 }
645
646
647 /*********************************************************************
648  *      _i64toa   (NTDLL.@)
649  *
650  * Converts a large integer to a string.
651  *
652  * RETURNS
653  *  str.
654  *
655  * NOTES
656  *  - Converts value to a Nul terminated string which is copied to str.
657  *  - The maximum length of the copied str is 65 bytes. If radix
658  *  is 10 and value is negative, the value is converted with sign.
659  *  - Does not check if radix is in the range of 2 to 36.
660  *  - If str is NULL it crashes, as the native function does.
661  *
662  * DIFFERENCES
663  * - The native DLL converts negative values (for base 10) wrong:
664  *|                     -1 is converted to -18446744073709551615
665  *|                     -2 is converted to -18446744073709551614
666  *|   -9223372036854775807 is converted to  -9223372036854775809
667  *|   -9223372036854775808 is converted to  -9223372036854775808
668  *   The native msvcrt _i64toa function and our ntdll _i64toa function
669  *   do not have this bug.
670  */
671 char * __cdecl _i64toa(
672     LONGLONG value, /* [I] Value to be converted */
673     char *str,      /* [O] Destination for the converted value */
674     int radix)      /* [I] Number base for conversion */
675 {
676     ULONGLONG val;
677     int negative;
678     char buffer[65];
679     char *pos;
680     int digit;
681
682     if (value < 0 && radix == 10) {
683         negative = 1;
684         val = -value;
685     } else {
686         negative = 0;
687         val = value;
688     } /* if */
689
690     pos = &buffer[64];
691     *pos = '\0';
692
693     do {
694         digit = val % radix;
695         val = val / radix;
696         if (digit < 10) {
697             *--pos = '0' + digit;
698         } else {
699             *--pos = 'a' + digit - 10;
700         } /* if */
701     } while (val != 0L);
702
703     if (negative) {
704         *--pos = '-';
705     } /* if */
706
707     memcpy(str, pos, &buffer[64] - pos + 1);
708     return str;
709 }
710
711
712 /*********************************************************************
713  *      _atoi64   (NTDLL.@)
714  *
715  * Convert a string to a large integer.
716  *
717  * PARAMS
718  *  str [I] String to be converted
719  *
720  * RETURNS
721  *  Success: The integer value represented by str.
722  *  Failure: 0. Note that this cannot be distinguished from a successful
723  *           return, if the string contains "0".
724  *
725  * NOTES
726  *  - Accepts: {whitespace} [+|-] {digits}
727  *  - No check is made for value overflow, only the lower 64 bits are assigned.
728  *  - If str is NULL it crashes, as the native function does.
729  */
730 LONGLONG __cdecl _atoi64( char *str )
731 {
732     ULONGLONG RunningTotal = 0;
733     char bMinus = 0;
734
735     while (*str == ' ' || (*str >= '\011' && *str <= '\015')) {
736         str++;
737     } /* while */
738
739     if (*str == '+') {
740         str++;
741     } else if (*str == '-') {
742         bMinus = 1;
743         str++;
744     } /* if */
745
746     while (*str >= '0' && *str <= '9') {
747         RunningTotal = RunningTotal * 10 + *str - '0';
748         str++;
749     } /* while */
750
751     return bMinus ? -RunningTotal : RunningTotal;
752 }
753
754
755 /*********************************************************************
756  *                  sprintf   (NTDLL.@)
757  */
758 int __cdecl NTDLL_sprintf( char *str, const char *format, ... )
759 {
760     int ret;
761     va_list valist;
762     va_start( valist, format );
763     ret = vsprintf( str, format, valist );
764     va_end( valist );
765     return ret;
766 }
767
768
769 /*********************************************************************
770  *                  vsprintf   (NTDLL.@)
771  */
772 int __cdecl NTDLL_vsprintf( char *str, const char *format, va_list args )
773 {
774     return vsprintf( str, format, args );
775 }
776
777
778 /*********************************************************************
779  *                  _snprintf   (NTDLL.@)
780  */
781 int __cdecl _snprintf( char *str, size_t len, const char *format, ... )
782 {
783     int ret;
784     va_list valist;
785     va_start( valist, format );
786     ret = vsnprintf( str, len, format, valist );
787     va_end( valist );
788     return ret;
789 }
790
791
792 /*********************************************************************
793  *                  _vsnprintf   (NTDLL.@)
794  */
795 int __cdecl _vsnprintf( char *str, size_t len, const char *format, va_list args )
796 {
797     return vsnprintf( str, len, format, args );
798 }
799
800
801 /*********************************************************************
802  *                  sscanf   (NTDLL.@)
803  */
804 int __cdecl NTDLL_sscanf( const char *str, const char *format, ... )
805 {
806     int ret;
807     va_list valist;
808     va_start( valist, format );
809     ret = vsscanf( str, format, valist );
810     va_end( valist );
811     return ret;
812 }
813
814
815 /*********************************************************************
816  *              _splitpath (NTDLL.@)
817  *
818  * Split a path into its component pieces.
819  *
820  * PARAMS
821  *  inpath [I] Path to split
822  *  drv    [O] Destination for drive component (e.g. "A:"). Must be at least 3 characters.
823  *  dir    [O] Destination for directory component. Should be at least MAX_PATH characters.
824  *  fname  [O] Destination for File name component. Should be at least MAX_PATH characters.
825  *  ext    [O] Destination for file extension component. Should be at least MAX_PATH characters.
826  *
827  * RETURNS
828  *  Nothing.
829  */
830 void __cdecl _splitpath(const char* inpath, char * drv, char * dir,
831                         char* fname, char * ext )
832 {
833     const char *p, *end;
834
835     if (inpath[0] && inpath[1] == ':')
836     {
837         if (drv)
838         {
839             drv[0] = inpath[0];
840             drv[1] = inpath[1];
841             drv[2] = 0;
842         }
843         inpath += 2;
844     }
845     else if (drv) drv[0] = 0;
846
847     /* look for end of directory part */
848     end = NULL;
849     for (p = inpath; *p; p++) if (*p == '/' || *p == '\\') end = p + 1;
850
851     if (end)  /* got a directory */
852     {
853         if (dir)
854         {
855             memcpy( dir, inpath, end - inpath );
856             dir[end - inpath] = 0;
857         }
858         inpath = end;
859     }
860     else if (dir) dir[0] = 0;
861
862     /* look for extension: what's after the last dot */
863     end = NULL;
864     for (p = inpath; *p; p++) if (*p == '.') end = p;
865
866     if (!end) end = p; /* there's no extension */
867
868     if (fname)
869     {
870         memcpy( fname, inpath, end - inpath );
871         fname[end - inpath] = 0;
872     }
873     if (ext) strcpy( ext, end );
874 }