GetClassInfo should return global classes even if the hInstance
[wine] / memory / string.c
1 /*
2  * String functions
3  *
4  * Copyright 1993 Yngvi Sigurjonsson
5  * Copyright 1996 Alexandre Julliard
6  */
7
8 #include <ctype.h>
9 #include <string.h>
10
11 #include "windef.h"
12 #include "winbase.h"
13 #include "wingdi.h"
14 #include "winuser.h"
15 #include "wine/winbase16.h"
16 #include "wine/winuser16.h"
17 #include "wine/keyboard16.h"
18 #include "wine/exception.h"
19 #include "wine/unicode.h"
20 #include "winerror.h"
21 #include "ldt.h"
22 #include "debugtools.h"
23 #include "winnls.h"
24
25 DEFAULT_DEBUG_CHANNEL(string);
26
27 /* Internaly used by strchr family functions */
28 static BOOL ChrCmpA( WORD word1, WORD word2);
29
30
31 /* filter for page-fault exceptions */
32 static WINE_EXCEPTION_FILTER(page_fault)
33 {
34     if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
35         return EXCEPTION_EXECUTE_HANDLER;
36     return EXCEPTION_CONTINUE_SEARCH;
37 }
38
39
40 /***********************************************************************
41  *           hmemcpy   (KERNEL.348)
42  */
43 void WINAPI hmemcpy16( LPVOID dst, LPCVOID src, LONG count )
44 {
45     memcpy( dst, src, count );
46 }
47
48
49 /***********************************************************************
50  *           lstrcat16   (KERNEL.89)
51  */
52 SEGPTR WINAPI lstrcat16( SEGPTR dst, LPCSTR src )
53 {
54     /* Windows does not check for NULL pointers here, so we don't either */
55     strcat( (LPSTR)PTR_SEG_TO_LIN(dst), src );
56     return dst;
57 }
58
59
60 /***********************************************************************
61  *           lstrcatA   (KERNEL32.599)
62  */
63 LPSTR WINAPI lstrcatA( LPSTR dst, LPCSTR src )
64 {
65     __TRY
66     {
67         strcat( dst, src );
68     }
69     __EXCEPT(page_fault)
70     {
71         SetLastError( ERROR_INVALID_PARAMETER );
72         return NULL;
73     }
74     __ENDTRY
75     return dst;
76 }
77
78
79 /***********************************************************************
80  *           lstrcatW   (KERNEL32.600)
81  */
82 LPWSTR WINAPI lstrcatW( LPWSTR dst, LPCWSTR src )
83 {
84     __TRY
85     {
86         strcatW( dst, src );
87     }
88     __EXCEPT(page_fault)
89     {
90         SetLastError( ERROR_INVALID_PARAMETER );
91         return NULL;
92     }
93     __ENDTRY
94     return dst;
95 }
96
97
98 /***********************************************************************
99  *           lstrcatn16   (KERNEL.352)
100  */
101 SEGPTR WINAPI lstrcatn16( SEGPTR dst, LPCSTR src, INT16 n )
102 {
103     LPSTR p = (LPSTR)PTR_SEG_TO_LIN(dst);
104
105     while (*p) p++;
106     if ((n -= (p - (LPSTR)PTR_SEG_TO_LIN(dst))) <= 0) return dst;
107     lstrcpynA( p, src, n );
108     return dst;
109 }
110
111
112 /***********************************************************************
113  *           lstrcmp16   (USER.430)
114  */
115 INT16 WINAPI lstrcmp16( LPCSTR str1, LPCSTR str2 )
116 {
117     return (INT16)strcmp( str1, str2 );
118 }
119
120
121 /***********************************************************************
122  *           lstrcmpA   (KERNEL.602)
123  */
124 INT WINAPI lstrcmpA( LPCSTR str1, LPCSTR str2 )
125 {
126     return CompareStringA(LOCALE_SYSTEM_DEFAULT,0,str1,-1,str2,-1) - 2 ;
127 }
128
129
130 /***********************************************************************
131  *           lstrcmpW   (KERNEL.603)
132  * FIXME : should call CompareStringW, when it is implemented.
133  *    This implementation is not "word sort", as it should.
134  */
135 INT WINAPI lstrcmpW( LPCWSTR str1, LPCWSTR str2 )
136 {
137     TRACE("%s and %s\n",
138                    debugstr_w (str1), debugstr_w (str2));
139     if (!str1 || !str2) {
140         SetLastError(ERROR_INVALID_PARAMETER);
141         return 0;
142     }
143     while (*str1 && (*str1 == *str2)) { str1++; str2++; }
144     return (INT)(*str1 - *str2);
145 }
146
147
148 /***********************************************************************
149  *           lstrcmpi16   (USER.471)
150  */
151 INT16 WINAPI lstrcmpi16( LPCSTR str1, LPCSTR str2 )
152 {
153     return (INT16)lstrcmpiA( str1, str2 );
154 }
155
156
157 /***********************************************************************
158  *           lstrcmpiA   (KERNEL32.605)
159  */
160 INT WINAPI lstrcmpiA( LPCSTR str1, LPCSTR str2 )
161 {    TRACE("strcmpi %s and %s\n",
162                    debugstr_a (str1), debugstr_a (str2));
163     return CompareStringA(LOCALE_SYSTEM_DEFAULT,NORM_IGNORECASE,str1,-1,str2,-1)-2;
164 }
165
166
167 /***********************************************************************
168  *           lstrcmpiW   (KERNEL32.606)
169  */
170 INT WINAPI lstrcmpiW( LPCWSTR str1, LPCWSTR str2 )
171 {
172     if (!str1 || !str2) {
173         SetLastError(ERROR_INVALID_PARAMETER);
174         return 0;
175     }
176     return strcmpiW( str1, str2 );
177 }
178
179
180 /***********************************************************************
181  *           lstrcpy16   (KERNEL.88)
182  */
183 SEGPTR WINAPI lstrcpy16( SEGPTR dst, LPCSTR src )
184 {
185     if (!lstrcpyA( PTR_SEG_TO_LIN(dst), src )) dst = 0;
186     return dst;
187 }
188
189
190 /***********************************************************************
191  *           lstrcpyA   (KERNEL32.608)
192  */
193 LPSTR WINAPI lstrcpyA( LPSTR dst, LPCSTR src )
194 {
195     __TRY
196     {
197         /* this is how Windows does it */
198         memmove( dst, src, strlen(src)+1 );
199     }
200     __EXCEPT(page_fault)
201     {
202         ERR("(%p, %p): page fault occurred ! Caused by bug ?\n", dst, src);
203         SetLastError( ERROR_INVALID_PARAMETER );
204         return NULL;
205     }
206     __ENDTRY
207     return dst;
208 }
209
210
211 /***********************************************************************
212  *           lstrcpyW   (KERNEL32.609)
213  */
214 LPWSTR WINAPI lstrcpyW( LPWSTR dst, LPCWSTR src )
215 {
216     __TRY
217     {
218         strcpyW( dst, src );
219     }
220     __EXCEPT(page_fault)
221     {
222         SetLastError( ERROR_INVALID_PARAMETER );
223         return NULL;
224     }
225     __ENDTRY
226     return dst;
227 }
228
229
230 /***********************************************************************
231  *           lstrcpyn16   (KERNEL.353)
232  */
233 SEGPTR WINAPI lstrcpyn16( SEGPTR dst, LPCSTR src, INT16 n )
234 {
235     lstrcpynA( (LPSTR)PTR_SEG_TO_LIN(dst), src, n );
236     return dst;
237 }
238
239
240 /***********************************************************************
241  *           lstrcpynA   (KERNEL32.611)
242  * Note: this function differs from the UNIX strncpy, it _always_ writes
243  * a terminating \0
244  */
245 LPSTR WINAPI lstrcpynA( LPSTR dst, LPCSTR src, INT n )
246 {
247     LPSTR p = dst;
248     TRACE("(%p, %s, %i)\n", dst, debugstr_an(src,n), n);
249     /* In real windows the whole function is protected by an exception handler
250      * that returns ERROR_INVALID_PARAMETER on faulty parameters
251      * We currently just check for NULL.
252      */
253     if (!dst || !src) {
254         SetLastError(ERROR_INVALID_PARAMETER);
255         return 0;
256     }
257     while ((n-- > 1) && *src) *p++ = *src++;
258     if (n >= 0) *p = 0;
259     return dst;
260 }
261
262
263 /***********************************************************************
264  *           lstrcpynW   (KERNEL32.612)
265  * Note: this function differs from the UNIX strncpy, it _always_ writes
266  * a terminating \0
267  */
268 LPWSTR WINAPI lstrcpynW( LPWSTR dst, LPCWSTR src, INT n )
269 {
270     LPWSTR p = dst;
271     TRACE("(%p, %s, %i)\n", dst,  debugstr_wn(src,n), n);
272     /* In real windows the whole function is protected by an exception handler
273      * that returns ERROR_INVALID_PARAMETER on faulty parameters
274      * We currently just check for NULL.
275      */
276     if (!dst || !src) {
277         SetLastError(ERROR_INVALID_PARAMETER);
278         return 0;
279     }
280     while ((n-- > 1) && *src) *p++ = *src++;
281     if (n >= 0) *p = 0;
282     return dst;
283 }
284
285
286 /***********************************************************************
287  *           lstrlen16   (KERNEL.90)
288  */
289 INT16 WINAPI lstrlen16( LPCSTR str )
290 {
291     return (INT16)lstrlenA( str );
292 }
293
294
295 /***********************************************************************
296  *           lstrlenA   (KERNEL32.614)
297  */
298 INT WINAPI lstrlenA( LPCSTR str )
299 {
300     INT ret;
301     __TRY
302     {
303         ret = strlen(str);
304     }
305     __EXCEPT(page_fault)
306     {
307         SetLastError( ERROR_INVALID_PARAMETER );
308         return 0;
309     }
310     __ENDTRY
311     return ret;
312 }
313
314
315 /***********************************************************************
316  *           lstrlenW   (KERNEL32.615)
317  */
318 INT WINAPI lstrlenW( LPCWSTR str )
319 {
320     INT ret;
321     __TRY
322     {
323         ret = strlenW(str);
324     }
325     __EXCEPT(page_fault)
326     {
327         SetLastError( ERROR_INVALID_PARAMETER );
328         return 0;
329     }
330     __ENDTRY
331     return ret;
332 }
333
334
335 /***********************************************************************
336  *           lstrcpyAtoW   (Not a Windows API)
337  */
338 LPWSTR WINAPI lstrcpyAtoW( LPWSTR dst, LPCSTR src )
339 {
340     MultiByteToWideChar( CP_ACP, 0, src, -1, dst, 0x7fffffff );
341     return dst;
342 }
343
344
345 /***********************************************************************
346  *           lstrcpyWtoA   (Not a Windows API)
347  */
348 LPSTR WINAPI lstrcpyWtoA( LPSTR dst, LPCWSTR src )
349 {
350     WideCharToMultiByte( CP_ACP, 0, src, -1, dst, 0x7fffffff, NULL, NULL );
351     return dst;
352 }
353
354
355 /***********************************************************************
356  *           lstrcpynAtoW   (Not a Windows API)
357  * Note: this function differs from the UNIX strncpy, it _always_ writes
358  * a terminating \0
359  */
360 LPWSTR WINAPI lstrcpynAtoW( LPWSTR dst, LPCSTR src, INT n )
361 {
362     if (n > 0 && !MultiByteToWideChar( CP_ACP, 0, src, -1, dst, n )) dst[n-1] = 0;
363     return dst;
364 }
365
366
367 /***********************************************************************
368  *           lstrcpynWtoA   (Not a Windows API)
369  * Note: this function differs from the UNIX strncpy, it _always_ writes
370  * a terminating \0
371  *
372  * The terminating zero should be written at the end of the string, not
373  * the end of the buffer, as some programs specify the wrong size for 
374  * the buffer (eg. winnt's sol.exe)
375  */
376 LPSTR WINAPI lstrcpynWtoA( LPSTR dst, LPCWSTR src, INT n )
377 {
378     if (n > 0 && !WideCharToMultiByte( CP_ACP, 0, src, -1, dst, n, NULL, NULL )) dst[n-1] = 0;
379     return dst;
380 }
381
382 /***********************************************************************
383  *           UnicodeToAnsi   (KERNEL.434)
384  */
385 INT16 WINAPI UnicodeToAnsi16( LPCWSTR src, LPSTR dst, INT16 codepage )
386 {
387     if ( codepage == -1 )
388         codepage = CP_ACP;
389
390     return WideCharToMultiByte( codepage, 0, src, -1, dst, 0x7fffffff, NULL, NULL );
391 }
392
393
394 /***********************************************************************
395  *           Copy   (GDI.250)
396  */
397 void WINAPI Copy16( LPVOID src, LPVOID dst, WORD size )
398 {
399     memcpy( dst, src, size );
400 }
401
402 /***********************************************************************
403  *           AnsiToOem16   (KEYBOARD.5)
404  */
405 INT16 WINAPI AnsiToOem16( LPCSTR s, LPSTR d )
406 {
407     CharToOemA( s, d );
408     return -1;
409 }
410
411
412 /***********************************************************************
413  *           OemToAnsi16   (KEYBOARD.6)
414  */
415 INT16 WINAPI OemToAnsi16( LPCSTR s, LPSTR d )
416 {
417     OemToCharA( s, d );
418     return -1;
419 }
420
421
422 /***********************************************************************
423  *           AnsiToOemBuff16   (KEYBOARD.134)
424  */
425 void WINAPI AnsiToOemBuff16( LPCSTR s, LPSTR d, UINT16 len )
426 {
427     if (len != 0) CharToOemBuffA( s, d, len );
428 }
429
430
431 /***********************************************************************
432  *           OemToAnsiBuff16   (KEYBOARD.135)
433  */
434 void WINAPI OemToAnsiBuff16( LPCSTR s, LPSTR d, UINT16 len )
435 {
436     if (len != 0) OemToCharBuffA( s, d, len );
437 }
438
439
440 /***********************************************************************
441  *           CharToOemA   (USER32.37)
442  */
443 BOOL WINAPI CharToOemA( LPCSTR s, LPSTR d )
444 {
445     if ( !s || !d ) return TRUE;
446     return CharToOemBuffA( s, d, strlen( s ) + 1 );
447 }
448
449
450 /***********************************************************************
451  *           CharToOemBuffA   (USER32.38)
452  */
453 BOOL WINAPI CharToOemBuffA( LPCSTR s, LPSTR d, DWORD len )
454 {
455     WCHAR *bufW;
456
457     bufW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
458     if( bufW )
459     {
460         MultiByteToWideChar( CP_ACP, 0, s, len, bufW, len );
461         WideCharToMultiByte( CP_OEMCP, 0, bufW, len, d, len, NULL, NULL );
462         HeapFree( GetProcessHeap(), 0, bufW );
463     }
464     return TRUE;
465 }
466
467
468 /***********************************************************************
469  *           CharToOemBuffW   (USER32.39)
470  */
471 BOOL WINAPI CharToOemBuffW( LPCWSTR s, LPSTR d, DWORD len )
472 {
473    if ( !s || !d ) return TRUE;
474     WideCharToMultiByte( CP_OEMCP, 0, s, len, d, len, NULL, NULL );
475     return TRUE;
476 }
477
478
479 /***********************************************************************
480  *           CharToOemW   (USER32.40)
481  */
482 BOOL WINAPI CharToOemW( LPCWSTR s, LPSTR d )
483 {
484     return CharToOemBuffW( s, d, strlenW( s ) + 1 );
485 }
486
487
488 /***********************************************************************
489  *           OemToCharA   (USER32.402)
490  */
491 BOOL WINAPI OemToCharA( LPCSTR s, LPSTR d )
492 {
493     return OemToCharBuffA( s, d, strlen( s ) + 1 );
494 }
495
496
497 /***********************************************************************
498  *           OemToCharBuffA   (USER32.403)
499  */
500 BOOL WINAPI OemToCharBuffA( LPCSTR s, LPSTR d, DWORD len )
501 {
502     WCHAR *bufW;
503
504     bufW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
505     if( bufW )
506     {
507         MultiByteToWideChar( CP_OEMCP, 0, s, len, bufW, len );
508         WideCharToMultiByte( CP_ACP, 0, bufW, len, d, len, NULL, NULL );
509         HeapFree( GetProcessHeap(), 0, bufW );
510     }
511     return TRUE;
512 }
513
514
515 /***********************************************************************
516  *           OemToCharBuffW   (USER32.404)
517  */
518 BOOL WINAPI OemToCharBuffW( LPCSTR s, LPWSTR d, DWORD len )
519 {
520     MultiByteToWideChar( CP_OEMCP, 0, s, len, d, len );
521     return TRUE;
522 }
523
524
525 /***********************************************************************
526  *           OemToCharW   (USER32.405)
527  */
528 BOOL WINAPI OemToCharW( LPCSTR s, LPWSTR d )
529 {
530     return OemToCharBuffW( s, d, strlen( s ) + 1 );
531 }
532
533 /***********************************************************************
534  *           lstrrchr   (Not a Windows API)
535  *
536  * This is the implementation meant to be invoked from within
537  * COMCTL32_StrRChrA and shell32(TODO)...
538  *
539  * Return a pointer to the last occurence of wMatch in lpStart
540  * not looking further than lpEnd...
541  */
542 LPSTR WINAPI lstrrchr( LPCSTR lpStart, LPCSTR lpEnd, WORD wMatch )
543 {
544   LPCSTR lpGotIt = NULL;
545
546   TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
547
548   if (!lpEnd) lpEnd = lpStart + strlen(lpStart);
549
550   for(; lpStart < lpEnd; lpStart = CharNextA(lpStart)) 
551     if (!ChrCmpA( GET_WORD(lpStart), wMatch)) 
552       lpGotIt = lpStart;
553     
554   return ((LPSTR)lpGotIt);
555 }
556
557 /***********************************************************************
558  *           ChrCmpW   
559  * This fuction returns FALSE if both words match, TRUE otherwise...
560  */
561 static BOOL ChrCmpW( WORD word1, WORD word2) {
562   return (word1 != word2);
563 }
564
565 /***********************************************************************
566  *           lstrrchrw    (Not a Windows API)
567  *
568  * This is the implementation meant to be invoked form within
569  * COMCTL32_StrRChrW and shell32(TODO)...
570  *
571  * Return a pointer to the last occurence of wMatch in lpStart
572  * not looking further than lpEnd...
573  */  
574 LPWSTR WINAPI lstrrchrw( LPCWSTR lpStart, LPCWSTR lpEnd, WORD wMatch )
575 {
576   LPCWSTR lpGotIt = NULL;
577
578   TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
579   if (!lpEnd) lpEnd = lpStart + lstrlenW(lpStart);
580
581   for(; lpStart < lpEnd; lpStart = CharNextW(lpStart)) 
582     if (!ChrCmpW( GET_WORD(lpStart), wMatch)) 
583       lpGotIt = lpStart;
584     
585   return (LPWSTR)lpGotIt;
586 }
587
588 /***********************************************************************
589  *           ChrCmpA   
590  * This fuction returns FALSE if both words match, TRUE otherwise...
591  */
592 static BOOL ChrCmpA( WORD word1, WORD word2) {
593   if (LOBYTE(word1) == LOBYTE(word2)) {
594     if (IsDBCSLeadByte(LOBYTE(word1))) {
595       return (word1 != word2);
596     }
597     return FALSE;
598   }
599   return TRUE;
600 }