Do not check for non NULL pointer before HeapFree'ing it. It's
[wine] / dlls / kernel / string.c
1 /*
2  * Kernel string functions
3  *
4  * Copyright 1993 Yngvi Sigurjonsson
5  * Copyright 1996 Alexandre Julliard
6  * Copyright 2001 Dmitry Timoshkov for CodeWeavers
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 #include "wine/port.h"
25
26 #include <ctype.h>
27 #include <stdarg.h>
28 #include <string.h>
29
30 #include "windef.h"
31 #include "winbase.h"
32 #include "excpt.h"
33 #include "wine/winbase16.h"
34 #include "wine/unicode.h"
35 #include "wine/exception.h"
36
37
38 static INT (WINAPI *pLoadStringA)(HINSTANCE, UINT, LPSTR, INT);
39 static INT (WINAPI *pwvsprintfA)(LPSTR, LPCSTR, va_list);
40
41 /* filter for page-fault exceptions */
42 static WINE_EXCEPTION_FILTER(page_fault)
43 {
44     if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
45         return EXCEPTION_EXECUTE_HANDLER;
46     return EXCEPTION_CONTINUE_SEARCH;
47 }
48
49
50 /***********************************************************************
51  * Helper for k32 family functions
52  */
53 static void *user32_proc_address(const char *proc_name)
54 {
55     static HMODULE hUser32;
56
57     if(!hUser32) hUser32 = LoadLibraryA("user32.dll");
58     return GetProcAddress(hUser32, proc_name);
59 }
60
61
62 /***********************************************************************
63  *              k32CharToOemBuffA   (KERNEL32.11)
64  */
65 BOOL WINAPI k32CharToOemBuffA(LPCSTR s, LPSTR d, DWORD len)
66 {
67     WCHAR *bufW;
68
69     if ((bufW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
70     {
71         MultiByteToWideChar( CP_ACP, 0, s, len, bufW, len );
72         WideCharToMultiByte( CP_OEMCP, 0, bufW, len, d, len, NULL, NULL );
73         HeapFree( GetProcessHeap(), 0, bufW );
74     }
75     return TRUE;
76 }
77
78
79 /***********************************************************************
80  *              k32CharToOemA   (KERNEL32.10)
81  */
82 BOOL WINAPI k32CharToOemA(LPCSTR s, LPSTR d)
83 {
84     if (!s || !d) return TRUE;
85     return k32CharToOemBuffA( s, d, strlen(s) + 1 );
86 }
87
88
89 /***********************************************************************
90  *              k32OemToCharBuffA   (KERNEL32.13)
91  */
92 BOOL WINAPI k32OemToCharBuffA(LPCSTR s, LPSTR d, DWORD len)
93 {
94     WCHAR *bufW;
95
96     if ((bufW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )))
97     {
98         MultiByteToWideChar( CP_OEMCP, 0, s, len, bufW, len );
99         WideCharToMultiByte( CP_ACP, 0, bufW, len, d, len, NULL, NULL );
100         HeapFree( GetProcessHeap(), 0, bufW );
101     }
102     return TRUE;
103 }
104
105
106 /***********************************************************************
107  *              k32OemToCharA   (KERNEL32.12)
108  */
109 BOOL WINAPI k32OemToCharA(LPCSTR s, LPSTR d)
110 {
111     return k32OemToCharBuffA( s, d, strlen(s) + 1 );
112 }
113
114
115 /**********************************************************************
116  *              k32LoadStringA   (KERNEL32.14)
117  */
118 INT WINAPI k32LoadStringA(HINSTANCE instance, UINT resource_id,
119                           LPSTR buffer, INT buflen)
120 {
121     if(!pLoadStringA) pLoadStringA = user32_proc_address("LoadStringA");
122     return pLoadStringA(instance, resource_id, buffer, buflen);
123 }
124
125
126 /***********************************************************************
127  *              k32wvsprintfA   (KERNEL32.16)
128  */
129 INT WINAPI k32wvsprintfA(LPSTR buffer, LPCSTR spec, va_list args)
130 {
131     if(!pwvsprintfA) pwvsprintfA = user32_proc_address("wvsprintfA");
132     return (*pwvsprintfA)(buffer, spec, args);
133 }
134
135
136 /***********************************************************************
137  *              k32wsprintfA   (KERNEL32.15)
138  */
139 INT WINAPIV k32wsprintfA(LPSTR buffer, LPCSTR spec, ...)
140 {
141     va_list args;
142     INT res;
143
144     va_start(args, spec);
145     res = k32wvsprintfA(buffer, spec, args);
146     va_end(args);
147     return res;
148 }
149
150
151 /***********************************************************************
152  *           hmemcpy   (KERNEL.348)
153  */
154 void WINAPI hmemcpy16( LPVOID dst, LPCVOID src, LONG count )
155 {
156     memcpy( dst, src, count );
157 }
158
159
160 /***********************************************************************
161  *           lstrcat   (KERNEL.89)
162  */
163 SEGPTR WINAPI lstrcat16( SEGPTR dst, LPCSTR src )
164 {
165     /* Windows does not check for NULL pointers here, so we don't either */
166     strcat( MapSL(dst), src );
167     return dst;
168 }
169
170
171 /***********************************************************************
172  *           lstrcat    (KERNEL32.@)
173  *           lstrcatA   (KERNEL32.@)
174  */
175 LPSTR WINAPI lstrcatA( LPSTR dst, LPCSTR src )
176 {
177     __TRY
178     {
179         strcat( dst, src );
180     }
181     __EXCEPT(page_fault)
182     {
183         SetLastError( ERROR_INVALID_PARAMETER );
184         return NULL;
185     }
186     __ENDTRY
187     return dst;
188 }
189
190
191 /***********************************************************************
192  *           lstrcatW   (KERNEL32.@)
193  */
194 LPWSTR WINAPI lstrcatW( LPWSTR dst, LPCWSTR src )
195 {
196     __TRY
197     {
198         strcatW( dst, src );
199     }
200     __EXCEPT(page_fault)
201     {
202         SetLastError( ERROR_INVALID_PARAMETER );
203         return NULL;
204     }
205     __ENDTRY
206     return dst;
207 }
208
209
210 /***********************************************************************
211  *           lstrcatn   (KERNEL.352)
212  */
213 SEGPTR WINAPI lstrcatn16( SEGPTR dst, LPCSTR src, INT16 n )
214 {
215     LPSTR p = MapSL(dst);
216     LPSTR start = p;
217
218     while (*p) p++;
219     if ((n -= (p - start)) <= 0) return dst;
220     lstrcpynA( p, src, n );
221     return dst;
222 }
223
224
225 /***********************************************************************
226  *           lstrcpy   (KERNEL.88)
227  */
228 SEGPTR WINAPI lstrcpy16( SEGPTR dst, LPCSTR src )
229 {
230     if (!lstrcpyA( MapSL(dst), src )) dst = 0;
231     return dst;
232 }
233
234
235 /***********************************************************************
236  *           lstrcpy    (KERNEL32.@)
237  *           lstrcpyA   (KERNEL32.@)
238  */
239 LPSTR WINAPI lstrcpyA( LPSTR dst, LPCSTR src )
240 {
241     __TRY
242     {
243         /* this is how Windows does it */
244         memmove( dst, src, strlen(src)+1 );
245     }
246     __EXCEPT(page_fault)
247     {
248         SetLastError( ERROR_INVALID_PARAMETER );
249         return NULL;
250     }
251     __ENDTRY
252     return dst;
253 }
254
255
256 /***********************************************************************
257  *           lstrcpyW   (KERNEL32.@)
258  */
259 LPWSTR WINAPI lstrcpyW( LPWSTR dst, LPCWSTR src )
260 {
261     __TRY
262     {
263         strcpyW( dst, src );
264     }
265     __EXCEPT(page_fault)
266     {
267         SetLastError( ERROR_INVALID_PARAMETER );
268         return NULL;
269     }
270     __ENDTRY
271     return dst;
272 }
273
274
275 /***********************************************************************
276  *           lstrcpyn   (KERNEL.353)
277  */
278 SEGPTR WINAPI lstrcpyn16( SEGPTR dst, LPCSTR src, INT16 n )
279 {
280     lstrcpynA( MapSL(dst), src, n );
281     return dst;
282 }
283
284
285 /***********************************************************************
286  *           lstrcpyn    (KERNEL32.@)
287  *           lstrcpynA   (KERNEL32.@)
288  *
289  * Note: this function differs from the UNIX strncpy, it _always_ writes
290  * a terminating \0.
291  *
292  * Note: n is an INT but Windows treats it as unsigned, and will happily
293  * copy a gazillion chars if n is negative.
294  */
295 LPSTR WINAPI lstrcpynA( LPSTR dst, LPCSTR src, INT n )
296 {
297     __TRY
298     {
299         LPSTR d = dst;
300         LPCSTR s = src;
301         UINT count = n;
302
303         while ((count > 1) && *s)
304         {
305             count--;
306             *d++ = *s++;
307         }
308         if (count) *d = 0;
309     }
310     __EXCEPT(page_fault)
311     {
312         SetLastError( ERROR_INVALID_PARAMETER );
313         return 0;
314     }
315     __ENDTRY
316     return dst;
317 }
318
319
320 /***********************************************************************
321  *           lstrcpynW   (KERNEL32.@)
322  *
323  * Note: this function differs from the UNIX strncpy, it _always_ writes
324  * a terminating \0
325  *
326  * Note: n is an INT but Windows treats it as unsigned, and will happily
327  * copy a gazillion chars if n is negative.
328  */
329 LPWSTR WINAPI lstrcpynW( LPWSTR dst, LPCWSTR src, INT n )
330 {
331     __TRY
332     {
333         LPWSTR d = dst;
334         LPCWSTR s = src;
335         UINT count = n;
336
337         while ((count > 1) && *s)
338         {
339             count--;
340             *d++ = *s++;
341         }
342         if (count) *d = 0;
343     }
344     __EXCEPT(page_fault)
345     {
346         SetLastError( ERROR_INVALID_PARAMETER );
347         return 0;
348     }
349     __ENDTRY
350     return dst;
351 }
352
353
354 /***********************************************************************
355  *           lstrlen   (KERNEL.90)
356  */
357 INT16 WINAPI lstrlen16( LPCSTR str )
358 {
359     return (INT16)lstrlenA( str );
360 }
361
362
363 /***********************************************************************
364  *           lstrlen    (KERNEL32.@)
365  *           lstrlenA   (KERNEL32.@)
366  */
367 INT WINAPI lstrlenA( LPCSTR str )
368 {
369     INT ret;
370     __TRY
371     {
372         ret = strlen(str);
373     }
374     __EXCEPT(page_fault)
375     {
376         SetLastError( ERROR_INVALID_PARAMETER );
377         return 0;
378     }
379     __ENDTRY
380     return ret;
381 }
382
383
384 /***********************************************************************
385  *           lstrlenW   (KERNEL32.@)
386  */
387 INT WINAPI lstrlenW( LPCWSTR str )
388 {
389     INT ret;
390     __TRY
391     {
392         ret = strlenW(str);
393     }
394     __EXCEPT(page_fault)
395     {
396         SetLastError( ERROR_INVALID_PARAMETER );
397         return 0;
398     }
399     __ENDTRY
400     return ret;
401 }
402
403
404 /***********************************************************************
405  *           UnicodeToAnsi   (KERNEL.434)
406  */
407 INT16 WINAPI UnicodeToAnsi16( LPCWSTR src, LPSTR dst, INT16 codepage )
408 {
409     if ( codepage == -1 ) codepage = CP_ACP;
410     return WideCharToMultiByte( codepage, 0, src, -1, dst, 0x7fffffff, NULL, NULL );
411 }
412
413
414 /***************************************************************************
415  *
416  * Win 2.x string functions now moved to USER
417  *
418  * We rather want to implement them here instead of doing Callouts
419  */
420
421 /***********************************************************************
422  *              Reserved1 (KERNEL.77)
423  */
424 SEGPTR WINAPI KERNEL_AnsiNext16(SEGPTR current)
425 {
426     return (*(char *)MapSL(current)) ? current + 1 : current;
427 }
428
429 /***********************************************************************
430  *              Reserved2(KERNEL.78)
431  */
432 SEGPTR WINAPI KERNEL_AnsiPrev16( SEGPTR start, SEGPTR current )
433 {
434     return (current==start)?start:current-1;
435 }
436
437 /***********************************************************************
438  *              Reserved3 (KERNEL.79)
439  */
440 SEGPTR WINAPI KERNEL_AnsiUpper16( SEGPTR strOrChar )
441 {
442     /* uppercase only one char if strOrChar < 0x10000 */
443     if (HIWORD(strOrChar))
444     {
445         char *s = MapSL(strOrChar);
446         while (*s)
447         {
448             *s = toupper(*s);
449             s++;
450         }
451         return strOrChar;
452     }
453     else return toupper((char)strOrChar);
454 }
455
456 /***********************************************************************
457  *              Reserved4 (KERNEL.80)
458  */
459 SEGPTR WINAPI KERNEL_AnsiLower16( SEGPTR strOrChar )
460 {
461     /* lowercase only one char if strOrChar < 0x10000 */
462     if (HIWORD(strOrChar))
463     {
464         char *s = MapSL(strOrChar);
465         while (*s)
466         {
467             *s = tolower(*s);
468             s++;
469         }
470         return strOrChar;
471     }
472     else return tolower((char)strOrChar);
473 }
474
475
476 /***********************************************************************
477  *              Reserved5 (KERNEL.87)
478  */
479 INT16 WINAPI KERNEL_lstrcmp16( LPCSTR str1, LPCSTR str2 )
480 {
481     return (INT16)strcmp( str1, str2 );
482 }