ntdll: Add RtlGetProductInfo stub.
[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 ULONG __cdecl NTDLL_strtoul( const char *nptr, char **endptr, int base )
462 {
463     return strtoul( nptr, endptr, base );
464 }
465
466
467 /*********************************************************************
468  *      _ultoa   (NTDLL.@)
469  *
470  * Convert an unsigned long integer to a string.
471  *
472  * RETURNS
473  *  str.
474  *
475  * NOTES
476  *  - Converts value to a Nul terminated string which is copied to str.
477  *  - The maximum length of the copied str is 33 bytes.
478  *  - Does not check if radix is in the range of 2 to 36.
479  *  - If str is NULL it crashes, as the native function does.
480  */
481 char * __cdecl _ultoa(
482     ULONG value,         /* [I] Value to be converted */
483     char *str,           /* [O] Destination for the converted value */
484     int radix)           /* [I] Number base for conversion */
485 {
486     char buffer[33];
487     char *pos;
488     int digit;
489
490     pos = &buffer[32];
491     *pos = '\0';
492
493     do {
494         digit = value % radix;
495         value = value / radix;
496         if (digit < 10) {
497             *--pos = '0' + digit;
498         } else {
499             *--pos = 'a' + digit - 10;
500         } /* if */
501     } while (value != 0L);
502
503     memcpy(str, pos, &buffer[32] - pos + 1);
504     return str;
505 }
506
507
508 /*********************************************************************
509  *      _ltoa   (NTDLL.@)
510  *
511  * Convert a long integer to a string.
512  *
513  * RETURNS
514  *  str.
515  *
516  * NOTES
517  *  - Converts value to a Nul terminated string which is copied to str.
518  *  - The maximum length of the copied str is 33 bytes. If radix
519  *  is 10 and value is negative, the value is converted with sign.
520  *  - Does not check if radix is in the range of 2 to 36.
521  *  - If str is NULL it crashes, as the native function does.
522  */
523 char * __cdecl _ltoa(
524     LONG value, /* [I] Value to be converted */
525     char *str,  /* [O] Destination for the converted value */
526     int radix)  /* [I] Number base for conversion */
527 {
528     ULONG val;
529     int negative;
530     char buffer[33];
531     char *pos;
532     int digit;
533
534     if (value < 0 && radix == 10) {
535         negative = 1;
536         val = -value;
537     } else {
538         negative = 0;
539         val = value;
540     } /* if */
541
542     pos = &buffer[32];
543     *pos = '\0';
544
545     do {
546         digit = val % radix;
547         val = val / radix;
548         if (digit < 10) {
549             *--pos = '0' + digit;
550         } else {
551             *--pos = 'a' + digit - 10;
552         } /* if */
553     } while (val != 0L);
554
555     if (negative) {
556         *--pos = '-';
557     } /* if */
558
559     memcpy(str, pos, &buffer[32] - pos + 1);
560     return str;
561 }
562
563
564 /*********************************************************************
565  *      _itoa    (NTDLL.@)
566  *
567  * Converts an integer to a string.
568  *
569  * RETURNS
570  *  str.
571  *
572  * NOTES
573  *  - Converts value to a '\0' terminated string which is copied to str.
574  *  - The maximum length of the copied str is 33 bytes. If radix
575  *  is 10 and value is negative, the value is converted with sign.
576  *  - Does not check if radix is in the range of 2 to 36.
577  *  - If str is NULL it crashes, as the native function does.
578  */
579 char * __cdecl _itoa(
580     int value, /* [I] Value to be converted */
581     char *str, /* [O] Destination for the converted value */
582     int radix) /* [I] Number base for conversion */
583 {
584     return _ltoa(value, str, radix);
585 }
586
587
588 /*********************************************************************
589  *      _ui64toa   (NTDLL.@)
590  *
591  * Converts a large unsigned integer to a string.
592  *
593  * RETURNS
594  *  str.
595  *
596  * NOTES
597  *  - Converts value to a '\0' terminated string which is copied to str.
598  *  - The maximum length of the copied str is 65 bytes.
599  *  - Does not check if radix is in the range of 2 to 36.
600  *  - If str is NULL it crashes, as the native function does.
601  */
602 char * __cdecl _ui64toa(
603     ULONGLONG value, /* [I] Value to be converted */
604     char *str,       /* [O] Destination for the converted value */
605     int radix)       /* [I] Number base for conversion */
606 {
607     char buffer[65];
608     char *pos;
609     int digit;
610
611     pos = &buffer[64];
612     *pos = '\0';
613
614     do {
615         digit = value % radix;
616         value = value / radix;
617         if (digit < 10) {
618             *--pos = '0' + digit;
619         } else {
620             *--pos = 'a' + digit - 10;
621         } /* if */
622     } while (value != 0L);
623
624     memcpy(str, pos, &buffer[64] - pos + 1);
625     return str;
626 }
627
628
629 /*********************************************************************
630  *      _i64toa   (NTDLL.@)
631  *
632  * Converts a large integer to a string.
633  *
634  * RETURNS
635  *  str.
636  *
637  * NOTES
638  *  - Converts value to a Nul terminated string which is copied to str.
639  *  - The maximum length of the copied str is 65 bytes. If radix
640  *  is 10 and value is negative, the value is converted with sign.
641  *  - Does not check if radix is in the range of 2 to 36.
642  *  - If str is NULL it crashes, as the native function does.
643  *
644  * DIFFERENCES
645  * - The native DLL converts negative values (for base 10) wrong:
646  *|                     -1 is converted to -18446744073709551615
647  *|                     -2 is converted to -18446744073709551614
648  *|   -9223372036854775807 is converted to  -9223372036854775809
649  *|   -9223372036854775808 is converted to  -9223372036854775808
650  *   The native msvcrt _i64toa function and our ntdll _i64toa function
651  *   do not have this bug.
652  */
653 char * __cdecl _i64toa(
654     LONGLONG value, /* [I] Value to be converted */
655     char *str,      /* [O] Destination for the converted value */
656     int radix)      /* [I] Number base for conversion */
657 {
658     ULONGLONG val;
659     int negative;
660     char buffer[65];
661     char *pos;
662     int digit;
663
664     if (value < 0 && radix == 10) {
665         negative = 1;
666         val = -value;
667     } else {
668         negative = 0;
669         val = value;
670     } /* if */
671
672     pos = &buffer[64];
673     *pos = '\0';
674
675     do {
676         digit = val % radix;
677         val = val / radix;
678         if (digit < 10) {
679             *--pos = '0' + digit;
680         } else {
681             *--pos = 'a' + digit - 10;
682         } /* if */
683     } while (val != 0L);
684
685     if (negative) {
686         *--pos = '-';
687     } /* if */
688
689     memcpy(str, pos, &buffer[64] - pos + 1);
690     return str;
691 }
692
693
694 /*********************************************************************
695  *      _atoi64   (NTDLL.@)
696  *
697  * Convert a string to a large integer.
698  *
699  * PARAMS
700  *  str [I] String to be converted
701  *
702  * RETURNS
703  *  Success: The integer value represented by str.
704  *  Failure: 0. Note that this cannot be distinguished from a successful
705  *           return, if the string contains "0".
706  *
707  * NOTES
708  *  - Accepts: {whitespace} [+|-] {digits}
709  *  - No check is made for value overflow, only the lower 64 bits are assigned.
710  *  - If str is NULL it crashes, as the native function does.
711  */
712 LONGLONG __cdecl _atoi64( const char *str )
713 {
714     ULONGLONG RunningTotal = 0;
715     char bMinus = 0;
716
717     while (*str == ' ' || (*str >= '\011' && *str <= '\015')) {
718         str++;
719     } /* while */
720
721     if (*str == '+') {
722         str++;
723     } else if (*str == '-') {
724         bMinus = 1;
725         str++;
726     } /* if */
727
728     while (*str >= '0' && *str <= '9') {
729         RunningTotal = RunningTotal * 10 + *str - '0';
730         str++;
731     } /* while */
732
733     return bMinus ? -RunningTotal : RunningTotal;
734 }
735
736
737 /*********************************************************************
738  *                  atoi   (NTDLL.@)
739  */
740 int __cdecl NTDLL_atoi( const char *nptr )
741 {
742     return _atoi64( nptr );
743 }
744
745
746 /*********************************************************************
747  *                  atol   (NTDLL.@)
748  */
749 LONG __cdecl NTDLL_atol( const char *nptr )
750 {
751     return _atoi64( nptr );
752 }
753
754
755 /*********************************************************************
756  *                  sscanf   (NTDLL.@)
757  */
758 int __cdecl NTDLL_sscanf( const char *str, const char *format, ... )
759 {
760     int ret;
761     va_list valist;
762     va_start( valist, format );
763     ret = vsscanf( str, format, valist );
764     va_end( valist );
765     return ret;
766 }
767
768
769 /*********************************************************************
770  *              _splitpath (NTDLL.@)
771  *
772  * Split a path into its component pieces.
773  *
774  * PARAMS
775  *  inpath [I] Path to split
776  *  drv    [O] Destination for drive component (e.g. "A:"). Must be at least 3 characters.
777  *  dir    [O] Destination for directory component. Should be at least MAX_PATH characters.
778  *  fname  [O] Destination for File name component. Should be at least MAX_PATH characters.
779  *  ext    [O] Destination for file extension component. Should be at least MAX_PATH characters.
780  *
781  * RETURNS
782  *  Nothing.
783  */
784 void __cdecl _splitpath(const char* inpath, char * drv, char * dir,
785                         char* fname, char * ext )
786 {
787     const char *p, *end;
788
789     if (inpath[0] && inpath[1] == ':')
790     {
791         if (drv)
792         {
793             drv[0] = inpath[0];
794             drv[1] = inpath[1];
795             drv[2] = 0;
796         }
797         inpath += 2;
798     }
799     else if (drv) drv[0] = 0;
800
801     /* look for end of directory part */
802     end = NULL;
803     for (p = inpath; *p; p++) if (*p == '/' || *p == '\\') end = p + 1;
804
805     if (end)  /* got a directory */
806     {
807         if (dir)
808         {
809             memcpy( dir, inpath, end - inpath );
810             dir[end - inpath] = 0;
811         }
812         inpath = end;
813     }
814     else if (dir) dir[0] = 0;
815
816     /* look for extension: what's after the last dot */
817     end = NULL;
818     for (p = inpath; *p; p++) if (*p == '.') end = p;
819
820     if (!end) end = p; /* there's no extension */
821
822     if (fname)
823     {
824         memcpy( fname, inpath, end - inpath );
825         fname[end - inpath] = 0;
826     }
827     if (ext) strcpy( ext, end );
828 }