Use HANDLE instead of HKEY in the NT API.
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include "config.h"
24
25 #include <ctype.h>
26 #include <stdarg.h>
27 #include <string.h>
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winternl.h"
32
33
34 /*********************************************************************
35  *                  _memicmp   (NTDLL.@)
36  *
37  * Compare two blocks of memory as strings, ignoring case.
38  *
39  * PARAMS
40  *  s1  [I] First string to compare to s2
41  *  s2  [I] Second string to compare to s1
42  *  len [I] Number of bytes to compare
43  *
44  * RETURNS
45  *  An integer less than, equal to, or greater than zero indicating that
46  *  s1 is less than, equal to or greater than s2 respectively.
47  *
48  * NOTES
49  *  Any Nul characters in s1 or s2 are ignored. This function always
50  *  compares up to len bytes or the first place where s1 and s2 differ.
51  */
52 INT __cdecl NTDLL__memicmp( LPCSTR s1, LPCSTR s2, DWORD len )
53 {
54     int ret = 0;
55     while (len--)
56     {
57         if ((ret = tolower(*s1) - tolower(*s2))) break;
58         s1++;
59         s2++;
60     }
61     return ret;
62 }
63
64
65 /*********************************************************************
66  *                  _strupr   (NTDLL.@)
67  *
68  * Convert a string to upper case.
69  *
70  * PARAMS
71  *  str [I/O] String to convert
72  *
73  * RETURNS
74  *  str. There is no error return, if str is NULL or invalid, this
75  *  function will crash.
76  */
77 LPSTR __cdecl _strupr( LPSTR str )
78 {
79     LPSTR ret = str;
80     for ( ; *str; str++) *str = toupper(*str);
81     return ret;
82 }
83
84
85 /*********************************************************************
86  *                  _strlwr   (NTDLL.@)
87  *
88  * Convert a string to lowercase
89  *
90  * PARAMS
91  *  str [I/O] String to convert
92  *
93  * RETURNS
94  *  str. There is no error return, if str is NULL or invalid, this
95  *  function will crash.
96  */
97 LPSTR __cdecl _strlwr( LPSTR str )
98 {
99     LPSTR ret = str;
100     for ( ; *str; str++) *str = tolower(*str);
101     return ret;
102 }
103
104
105 /*********************************************************************
106  *      _ultoa   (NTDLL.@)
107  *
108  * Convert an unsigned long integer to a string.
109  *
110  * RETURNS
111  *  str.
112  *
113  * NOTES
114  *  - Converts value to a Nul terminated string which is copied to str.
115  *  - The maximum length of the copied str is 33 bytes.
116  *  - Does not check if radix is in the range of 2 to 36.
117  *  - If str is NULL it crashes, as the native function does.
118  */
119 char * __cdecl _ultoa(
120     unsigned long value, /* [I] Value to be converted */
121     char *str,           /* [O] Destination for the converted value */
122     int radix)           /* [I] Number base for conversion */
123 {
124     char buffer[33];
125     char *pos;
126     int digit;
127
128     pos = &buffer[32];
129     *pos = '\0';
130
131     do {
132         digit = value % radix;
133         value = value / radix;
134         if (digit < 10) {
135             *--pos = '0' + digit;
136         } else {
137             *--pos = 'a' + digit - 10;
138         } /* if */
139     } while (value != 0L);
140
141     memcpy(str, pos, &buffer[32] - pos + 1);
142     return str;
143 }
144
145
146 /*********************************************************************
147  *      _ltoa   (NTDLL.@)
148  *
149  * Convert a long integer to a string.
150  *
151  * RETURNS
152  *  str.
153  *
154  * NOTES
155  *  - Converts value to a Nul terminated string which is copied to str.
156  *  - The maximum length of the copied str is 33 bytes. If radix
157  *  is 10 and value is negative, the value is converted with sign.
158  *  - Does not check if radix is in the range of 2 to 36.
159  *  - If str is NULL it crashes, as the native function does.
160  */
161 char * __cdecl _ltoa(
162     long value, /* [I] Value to be converted */
163     char *str,  /* [O] Destination for the converted value */
164     int radix)  /* [I] Number base for conversion */
165 {
166     unsigned long val;
167     int negative;
168     char buffer[33];
169     char *pos;
170     int digit;
171
172     if (value < 0 && radix == 10) {
173         negative = 1;
174         val = -value;
175     } else {
176         negative = 0;
177         val = value;
178     } /* if */
179
180     pos = &buffer[32];
181     *pos = '\0';
182
183     do {
184         digit = val % radix;
185         val = val / radix;
186         if (digit < 10) {
187             *--pos = '0' + digit;
188         } else {
189             *--pos = 'a' + digit - 10;
190         } /* if */
191     } while (val != 0L);
192
193     if (negative) {
194         *--pos = '-';
195     } /* if */
196
197     memcpy(str, pos, &buffer[32] - pos + 1);
198     return str;
199 }
200
201
202 /*********************************************************************
203  *      _itoa    (NTDLL.@)
204  *
205  * Converts an integer to a string.
206  *
207  * RETURNS
208  *  str.
209  *
210  * NOTES
211  *  - Converts value to a '\0' terminated string which is copied to str.
212  *  - The maximum length of the copied str is 33 bytes. If radix
213  *  is 10 and value is negative, the value is converted with sign.
214  *  - Does not check if radix is in the range of 2 to 36.
215  *  - If str is NULL it crashes, as the native function does.
216  */
217 char * __cdecl _itoa(
218     int value, /* [I] Value to be converted */
219     char *str, /* [O] Destination for the converted value */
220     int radix) /* [I] Number base for conversion */
221 {
222     return _ltoa(value, str, radix);
223 }
224
225
226 /*********************************************************************
227  *      _ui64toa   (NTDLL.@)
228  *
229  * Converts a large unsigned integer to a string.
230  *
231  * RETURNS
232  *  str.
233  *
234  * NOTES
235  *  - Converts value to a '\0' terminated string which is copied to str.
236  *  - The maximum length of the copied str is 65 bytes.
237  *  - Does not check if radix is in the range of 2 to 36.
238  *  - If str is NULL it crashes, as the native function does.
239  */
240 char * __cdecl _ui64toa(
241     ULONGLONG value, /* [I] Value to be converted */
242     char *str,       /* [O] Destination for the converted value */
243     int radix)       /* [I] Number base for conversion */
244 {
245     char buffer[65];
246     char *pos;
247     int digit;
248
249     pos = &buffer[64];
250     *pos = '\0';
251
252     do {
253         digit = value % radix;
254         value = value / radix;
255         if (digit < 10) {
256             *--pos = '0' + digit;
257         } else {
258             *--pos = 'a' + digit - 10;
259         } /* if */
260     } while (value != 0L);
261
262     memcpy(str, pos, &buffer[64] - pos + 1);
263     return str;
264 }
265
266
267 /*********************************************************************
268  *      _i64toa   (NTDLL.@)
269  *
270  * Converts a large integer to a string.
271  *
272  * RETURNS
273  *  str.
274  *
275  * NOTES
276  *  - Converts value to a Nul terminated string which is copied to str.
277  *  - The maximum length of the copied str is 65 bytes. If radix
278  *  is 10 and value is negative, the value is converted with sign.
279  *  - Does not check if radix is in the range of 2 to 36.
280  *  - If str is NULL it crashes, as the native function does.
281  *
282  * DIFFERENCES
283  * - The native DLL converts negative values (for base 10) wrong:
284  *|                     -1 is converted to -18446744073709551615
285  *|                     -2 is converted to -18446744073709551614
286  *|   -9223372036854775807 is converted to  -9223372036854775809
287  *|   -9223372036854775808 is converted to  -9223372036854775808
288  *   The native msvcrt _i64toa function and our ntdll _i64toa function
289  *   do not have this bug.
290  */
291 char * __cdecl _i64toa(
292     LONGLONG value, /* [I] Value to be converted */
293     char *str,      /* [O] Destination for the converted value */
294     int radix)      /* [I] Number base for conversion */
295 {
296     ULONGLONG val;
297     int negative;
298     char buffer[65];
299     char *pos;
300     int digit;
301
302     if (value < 0 && radix == 10) {
303         negative = 1;
304         val = -value;
305     } else {
306         negative = 0;
307         val = value;
308     } /* if */
309
310     pos = &buffer[64];
311     *pos = '\0';
312
313     do {
314         digit = val % radix;
315         val = val / radix;
316         if (digit < 10) {
317             *--pos = '0' + digit;
318         } else {
319             *--pos = 'a' + digit - 10;
320         } /* if */
321     } while (val != 0L);
322
323     if (negative) {
324         *--pos = '-';
325     } /* if */
326
327     memcpy(str, pos, &buffer[64] - pos + 1);
328     return str;
329 }
330
331
332 /*********************************************************************
333  *      _atoi64   (NTDLL.@)
334  *
335  * Convert a string to a large integer.
336  *
337  * PARAMS
338  *  str [I] String to be converted
339  *
340  * RETURNS
341  *  Success: The integer value represented by str.
342  *  Failure: 0. Note that this cannot be distinguished from a successful
343  *           return, if the string contains "0".
344  *
345  * NOTES
346  *  - Accepts: {whitespace} [+|-] {digits}
347  *  - No check is made for value overflow, only the lower 64 bits are assigned.
348  *  - If str is NULL it crashes, as the native function does.
349  */
350 LONGLONG __cdecl _atoi64( char *str )
351 {
352     ULONGLONG RunningTotal = 0;
353     char bMinus = 0;
354
355     while (*str == ' ' || (*str >= '\011' && *str <= '\015')) {
356         str++;
357     } /* while */
358
359     if (*str == '+') {
360         str++;
361     } else if (*str == '-') {
362         bMinus = 1;
363         str++;
364     } /* if */
365
366     while (*str >= '0' && *str <= '9') {
367         RunningTotal = RunningTotal * 10 + *str - '0';
368         str++;
369     } /* while */
370
371     return bMinus ? -RunningTotal : RunningTotal;
372 }
373
374
375 /*********************************************************************
376  *              _splitpath (NTDLL.@)
377  *
378  * Split a path into its component pieces.
379  *
380  * PARAMS
381  *  inpath [I] Path to split
382  *  drv    [O] Destination for drive component (e.g. "A:"). Must be at least 3 characters.
383  *  dir    [O] Destination for directory component. Should be at least MAX_PATH characters.
384  *  fname  [O] Destination for File name component. Should be at least MAX_PATH characters.
385  *  ext    [O] Destination for file extension component. Should be at least MAX_PATH characters.
386  */
387 void __cdecl _splitpath(const char* inpath, char * drv, char * dir,
388                         char* fname, char * ext )
389 {
390     const char *p, *end;
391
392     if (inpath[0] && inpath[1] == ':')
393     {
394         if (drv)
395         {
396             drv[0] = inpath[0];
397             drv[1] = inpath[1];
398             drv[2] = 0;
399         }
400         inpath += 2;
401     }
402     else if (drv) drv[0] = 0;
403
404     /* look for end of directory part */
405     end = NULL;
406     for (p = inpath; *p; p++) if (*p == '/' || *p == '\\') end = p + 1;
407
408     if (end)  /* got a directory */
409     {
410         if (dir)
411         {
412             memcpy( dir, inpath, end - inpath );
413             dir[end - inpath] = 0;
414         }
415         inpath = end;
416     }
417     else if (dir) dir[0] = 0;
418
419     /* look for extension: what's after the last dot */
420     end = NULL;
421     for (p = inpath; *p; p++) if (*p == '.') end = p;
422
423     if (!end) end = p; /* there's no extension */
424
425     if (fname)
426     {
427         memcpy( fname, inpath, end - inpath );
428         fname[end - inpath] = 0;
429     }
430     if (ext) strcpy( ext, end );
431 }