Moved most kernel string functions to dlls/kernel.
[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  *           lstrlen   (KERNEL.90)
284  */
285 INT16 WINAPI lstrlen16( LPCSTR str )
286 {
287     return (INT16)lstrlenA( str );
288 }
289
290
291 /***********************************************************************
292  *           lstrlen    (KERNEL32.@)
293  *           lstrlenA   (KERNEL32.@)
294  */
295 INT WINAPI lstrlenA( LPCSTR str )
296 {
297     INT ret;
298     __TRY
299     {
300         ret = strlen(str);
301     }
302     __EXCEPT(page_fault)
303     {
304         SetLastError( ERROR_INVALID_PARAMETER );
305         return 0;
306     }
307     __ENDTRY
308     return ret;
309 }
310
311
312 /***********************************************************************
313  *           lstrlenW   (KERNEL32.@)
314  */
315 INT WINAPI lstrlenW( LPCWSTR str )
316 {
317     INT ret;
318     __TRY
319     {
320         ret = strlenW(str);
321     }
322     __EXCEPT(page_fault)
323     {
324         SetLastError( ERROR_INVALID_PARAMETER );
325         return 0;
326     }
327     __ENDTRY
328     return ret;
329 }
330
331
332 /***********************************************************************
333  *           UnicodeToAnsi   (KERNEL.434)
334  */
335 INT16 WINAPI UnicodeToAnsi16( LPCWSTR src, LPSTR dst, INT16 codepage )
336 {
337     if ( codepage == -1 ) codepage = CP_ACP;
338     return WideCharToMultiByte( codepage, 0, src, -1, dst, 0x7fffffff, NULL, NULL );
339 }
340
341
342 /***************************************************************************
343  *
344  * Win 2.x string functions now moved to USER
345  *
346  * We rather want to implement them here instead of doing Callouts
347  */
348
349 /***********************************************************************
350  *              Reserved1 (KERNEL.77)
351  */
352 SEGPTR WINAPI KERNEL_AnsiNext16(SEGPTR current)
353 {
354     return (*(char *)MapSL(current)) ? current + 1 : current;
355 }
356
357 /***********************************************************************
358  *              Reserved2(KERNEL.78)
359  */
360 SEGPTR WINAPI KERNEL_AnsiPrev16( SEGPTR start, SEGPTR current )
361 {
362     return (current==start)?start:current-1;
363 }
364
365 /***********************************************************************
366  *              Reserved3 (KERNEL.79)
367  */
368 SEGPTR WINAPI KERNEL_AnsiUpper16( SEGPTR strOrChar )
369 {
370     /* uppercase only one char if strOrChar < 0x10000 */
371     if (HIWORD(strOrChar))
372     {
373         char *s = MapSL(strOrChar);
374         while (*s)
375         {
376             *s = toupper(*s);
377             s++;
378         }
379         return strOrChar;
380     }
381     else return toupper((char)strOrChar);
382 }
383
384 /***********************************************************************
385  *              Reserved4 (KERNEL.80)
386  */
387 SEGPTR WINAPI KERNEL_AnsiLower16( SEGPTR strOrChar )
388 {
389     /* lowercase only one char if strOrChar < 0x10000 */
390     if (HIWORD(strOrChar))
391     {
392         char *s = MapSL(strOrChar);
393         while (*s)
394         {
395             *s = tolower(*s);
396             s++;
397         }
398         return strOrChar;
399     }
400     else return tolower((char)strOrChar);
401 }
402
403
404 /***********************************************************************
405  *              Reserved5 (KERNEL.87)
406  */
407 INT16 WINAPI KERNEL_lstrcmp16( LPCSTR str1, LPCSTR str2 )
408 {
409     return (INT16)strcmp( str1, str2 );
410 }