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