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