Align data to proper size.
[wine] / memory / string.c
1 /*
2  * String functions
3  *
4  * Copyright 1993 Yngvi Sigurjonsson
5  * Copyright 1996 Alexandre Julliard
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include <ctype.h>
23 #include <string.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "wine/winbase16.h"
28 #include "wine/exception.h"
29 #include "wine/unicode.h"
30 #include "winerror.h"
31 #include "winnls.h"
32 #include "excpt.h"
33 #include "wine/debug.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(string);
36
37 /* filter for page-fault exceptions */
38 static WINE_EXCEPTION_FILTER(page_fault)
39 {
40     if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
41         return EXCEPTION_EXECUTE_HANDLER;
42     return EXCEPTION_CONTINUE_SEARCH;
43 }
44
45
46 /***********************************************************************
47  *           hmemcpy   (KERNEL.348)
48  */
49 void WINAPI hmemcpy16( LPVOID dst, LPCVOID src, LONG count )
50 {
51     memcpy( dst, src, count );
52 }
53
54
55 /***********************************************************************
56  *           lstrcat   (KERNEL.89)
57  */
58 SEGPTR WINAPI lstrcat16( SEGPTR dst, LPCSTR src )
59 {
60     /* Windows does not check for NULL pointers here, so we don't either */
61     strcat( MapSL(dst), src );
62     return dst;
63 }
64
65
66 /***********************************************************************
67  *           lstrcat    (KERNEL32.@)
68  *           lstrcatA   (KERNEL32.@)
69  */
70 LPSTR WINAPI lstrcatA( LPSTR dst, LPCSTR src )
71 {
72     __TRY
73     {
74         strcat( dst, src );
75     }
76     __EXCEPT(page_fault)
77     {
78         SetLastError( ERROR_INVALID_PARAMETER );
79         return NULL;
80     }
81     __ENDTRY
82     return dst;
83 }
84
85
86 /***********************************************************************
87  *           lstrcatW   (KERNEL32.@)
88  */
89 LPWSTR WINAPI lstrcatW( LPWSTR dst, LPCWSTR src )
90 {
91     __TRY
92     {
93         strcatW( dst, src );
94     }
95     __EXCEPT(page_fault)
96     {
97         SetLastError( ERROR_INVALID_PARAMETER );
98         return NULL;
99     }
100     __ENDTRY
101     return dst;
102 }
103
104
105 /***********************************************************************
106  *           lstrcatn   (KERNEL.352)
107  */
108 SEGPTR WINAPI lstrcatn16( SEGPTR dst, LPCSTR src, INT16 n )
109 {
110     LPSTR p = MapSL(dst);
111     LPSTR start = p;
112
113     while (*p) p++;
114     if ((n -= (p - start)) <= 0) return dst;
115     lstrcpynA( p, src, n );
116     return dst;
117 }
118
119
120 /***********************************************************************
121  *           lstrcpy   (KERNEL.88)
122  */
123 SEGPTR WINAPI lstrcpy16( SEGPTR dst, LPCSTR src )
124 {
125     if (!lstrcpyA( MapSL(dst), src )) dst = 0;
126     return dst;
127 }
128
129
130 /***********************************************************************
131  *           lstrcpy    (KERNEL32.@)
132  *           lstrcpyA   (KERNEL32.@)
133  */
134 LPSTR WINAPI lstrcpyA( LPSTR dst, LPCSTR src )
135 {
136     __TRY
137     {
138         /* this is how Windows does it */
139         memmove( dst, src, strlen(src)+1 );
140     }
141     __EXCEPT(page_fault)
142     {
143         ERR("(%p, %p): page fault occurred ! Caused by bug ?\n", dst, src);
144         SetLastError( ERROR_INVALID_PARAMETER );
145         return NULL;
146     }
147     __ENDTRY
148     return dst;
149 }
150
151
152 /***********************************************************************
153  *           lstrcpyW   (KERNEL32.@)
154  */
155 LPWSTR WINAPI lstrcpyW( LPWSTR dst, LPCWSTR src )
156 {
157     __TRY
158     {
159         strcpyW( dst, src );
160     }
161     __EXCEPT(page_fault)
162     {
163         SetLastError( ERROR_INVALID_PARAMETER );
164         return NULL;
165     }
166     __ENDTRY
167     return dst;
168 }
169
170
171 /***********************************************************************
172  *           lstrcpyn   (KERNEL.353)
173  */
174 SEGPTR WINAPI lstrcpyn16( SEGPTR dst, LPCSTR src, INT16 n )
175 {
176     lstrcpynA( MapSL(dst), src, n );
177     return dst;
178 }
179
180
181 /***********************************************************************
182  *           lstrcpyn    (KERNEL32.@)
183  *           lstrcpynA   (KERNEL32.@)
184  *
185  * Note: this function differs from the UNIX strncpy, it _always_ writes
186  * a terminating \0.
187  *
188  * Note: n is an INT but Windows treats it as unsigned, and will happily
189  * copy a gazillion chars if n is negative.
190  */
191 LPSTR WINAPI lstrcpynA( LPSTR dst, LPCSTR src, INT n )
192 {
193     LPSTR p = dst;
194     UINT count = n;
195
196     TRACE("(%p, %s, %i)\n", dst, debugstr_a(src), n);
197
198     /* In real windows the whole function is protected by an exception handler
199      * that returns ERROR_INVALID_PARAMETER on faulty parameters
200      * We currently just check for NULL.
201      */
202     if (!dst || !src) {
203         SetLastError(ERROR_INVALID_PARAMETER);
204         return 0;
205     }
206     while ((count > 1) && *src)
207     {
208         count--;
209         *p++ = *src++;
210     }
211     if (count) *p = 0;
212     return dst;
213 }
214
215
216 /***********************************************************************
217  *           lstrcpynW   (KERNEL32.@)
218  *
219  * Note: this function differs from the UNIX strncpy, it _always_ writes
220  * a terminating \0
221  *
222  * Note: n is an INT but Windows treats it as unsigned, and will happily
223  * copy a gazillion chars if n is negative.
224  */
225 LPWSTR WINAPI lstrcpynW( LPWSTR dst, LPCWSTR src, INT n )
226 {
227     LPWSTR p = dst;
228     UINT count = n;
229
230     TRACE("(%p, %s, %i)\n", dst,  debugstr_w(src), n);
231
232     /* In real windows the whole function is protected by an exception handler
233      * that returns ERROR_INVALID_PARAMETER on faulty parameters
234      * We currently just check for NULL.
235      */
236     if (!dst || !src) {
237         SetLastError(ERROR_INVALID_PARAMETER);
238         return 0;
239     }
240     while ((count > 1) && *src)
241     {
242         count--;
243         *p++ = *src++;
244     }
245     if (count) *p = 0;
246     return dst;
247 }
248
249
250 /***********************************************************************
251  *           lstrlen   (KERNEL.90)
252  */
253 INT16 WINAPI lstrlen16( LPCSTR str )
254 {
255     return (INT16)lstrlenA( str );
256 }
257
258
259 /***********************************************************************
260  *           lstrlen    (KERNEL32.@)
261  *           lstrlenA   (KERNEL32.@)
262  */
263 INT WINAPI lstrlenA( LPCSTR str )
264 {
265     INT ret;
266     __TRY
267     {
268         ret = strlen(str);
269     }
270     __EXCEPT(page_fault)
271     {
272         SetLastError( ERROR_INVALID_PARAMETER );
273         return 0;
274     }
275     __ENDTRY
276     return ret;
277 }
278
279
280 /***********************************************************************
281  *           lstrlenW   (KERNEL32.@)
282  */
283 INT WINAPI lstrlenW( LPCWSTR str )
284 {
285     INT ret;
286     __TRY
287     {
288         ret = strlenW(str);
289     }
290     __EXCEPT(page_fault)
291     {
292         SetLastError( ERROR_INVALID_PARAMETER );
293         return 0;
294     }
295     __ENDTRY
296     return ret;
297 }
298
299
300 /***********************************************************************
301  *           UnicodeToAnsi   (KERNEL.434)
302  */
303 INT16 WINAPI UnicodeToAnsi16( LPCWSTR src, LPSTR dst, INT16 codepage )
304 {
305     if ( codepage == -1 )
306         codepage = CP_ACP;
307
308     return WideCharToMultiByte( codepage, 0, src, -1, dst, 0x7fffffff, NULL, NULL );
309 }