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