Share the system heap between different address spaces. Made process
[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 "wine/winbase16.h"
12 #include "wine/winuser16.h"
13 #include "winbase.h"
14 #include "winuser.h"
15 #include "wine/keyboard16.h"
16 #include "wine/exception.h"
17 #include "winerror.h"
18 #include "crtdll.h"
19 #include "ldt.h"
20 #include "debugtools.h"
21 #include "winnls.h"
22
23 DEFAULT_DEBUG_CHANNEL(string)
24
25 static const BYTE STRING_Oem2Ansi[256] =
26 "\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\244"
27 "\020\021\022\023\266\247\026\027\030\031\032\033\034\035\036\037"
28 "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
29 "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
30 "\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
31 "\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
32 "\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
33 "\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
34 "\307\374\351\342\344\340\345\347\352\353\350\357\356\354\304\305"
35 "\311\346\306\364\366\362\373\371\377\326\334\242\243\245\120\203"
36 "\341\355\363\372\361\321\252\272\277\137\254\275\274\241\253\273"
37 "\137\137\137\246\246\246\246\053\053\246\246\053\053\053\053\053"
38 "\053\055\055\053\055\053\246\246\053\053\055\055\246\055\053\055"
39 "\055\055\055\053\053\053\053\053\053\053\053\137\137\246\137\137"
40 "\137\337\137\266\137\137\265\137\137\137\137\137\137\137\137\137"
41 "\137\261\137\137\137\137\367\137\260\225\267\137\156\262\137\137";
42
43 static const BYTE STRING_Ansi2Oem[256] =
44 "\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017"
45 "\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
46 "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
47 "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
48 "\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
49 "\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
50 "\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
51 "\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
52 "\200\201\054\237\054\137\375\374\210\045\123\074\117\215\216\217"
53 "\220\140\047\042\042\371\055\137\230\231\163\076\157\235\236\131"
54 "\040\255\233\234\017\235\335\025\042\143\246\256\252\055\162\137"
55 "\370\361\375\063\047\346\024\372\054\061\247\257\254\253\137\250"
56 "\101\101\101\101\216\217\222\200\105\220\105\105\111\111\111\111"
57 "\104\245\117\117\117\117\231\170\117\125\125\125\232\131\137\341"
58 "\205\240\203\141\204\206\221\207\212\202\210\211\215\241\214\213"
59 "\144\244\225\242\223\157\224\366\157\227\243\226\201\171\137\230";
60
61 #define OEM_TO_ANSI(ch) (STRING_Oem2Ansi[(unsigned char)(ch)])
62 #define ANSI_TO_OEM(ch) (STRING_Ansi2Oem[(unsigned char)(ch)])
63
64 /* Internaly used by strchr family functions */
65 static BOOL ChrCmpA( WORD word1, WORD word2);
66
67
68 /* filter for page-fault exceptions */
69 static WINE_EXCEPTION_FILTER(page_fault)
70 {
71     if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
72         return EXCEPTION_EXECUTE_HANDLER;
73     return EXCEPTION_CONTINUE_SEARCH;
74 }
75
76
77 /***********************************************************************
78  *           hmemcpy   (KERNEL.348)
79  */
80 void WINAPI hmemcpy16( LPVOID dst, LPCVOID src, LONG count )
81 {
82     memcpy( dst, src, count );
83 }
84
85
86 /***********************************************************************
87  *           lstrcat16   (KERNEL.89)
88  */
89 SEGPTR WINAPI lstrcat16( SEGPTR dst, LPCSTR src )
90 {
91     /* Windows does not check for NULL pointers here, so we don't either */
92     strcat( (LPSTR)PTR_SEG_TO_LIN(dst), src );
93     return dst;
94 }
95
96
97 /***********************************************************************
98  *           lstrcatA   (KERNEL32.599)
99  */
100 LPSTR WINAPI lstrcatA( LPSTR dst, LPCSTR src )
101 {
102     __TRY
103     {
104         strcat( dst, src );
105     }
106     __EXCEPT(page_fault)
107     {
108         SetLastError( ERROR_INVALID_PARAMETER );
109         return NULL;
110     }
111     __ENDTRY
112     return dst;
113 }
114
115
116 /***********************************************************************
117  *           lstrcatW   (KERNEL32.600)
118  */
119 LPWSTR WINAPI lstrcatW( LPWSTR dst, LPCWSTR src )
120 {
121     __TRY
122     {
123         CRTDLL_wcscat( dst, src );
124     }
125     __EXCEPT(page_fault)
126     {
127         SetLastError( ERROR_INVALID_PARAMETER );
128         return NULL;
129     }
130     __ENDTRY
131     return dst;
132 }
133
134
135 /***********************************************************************
136  *           lstrcatn16   (KERNEL.352)
137  */
138 SEGPTR WINAPI lstrcatn16( SEGPTR dst, LPCSTR src, INT16 n )
139 {
140     LPSTR p = (LPSTR)PTR_SEG_TO_LIN(dst);
141
142     while (*p) p++;
143     if ((n -= (p - (LPSTR)PTR_SEG_TO_LIN(dst))) <= 0) return dst;
144     lstrcpynA( p, src, n );
145     return dst;
146 }
147
148
149 /***********************************************************************
150  *           lstrcmp16   (USER.430)
151  */
152 INT16 WINAPI lstrcmp16( LPCSTR str1, LPCSTR str2 )
153 {
154     return (INT16)strcmp( str1, str2 );
155 }
156
157
158 /***********************************************************************
159  *           lstrcmp32A   (KERNEL.602)
160  */
161 INT WINAPI lstrcmpA( LPCSTR str1, LPCSTR str2 )
162 {
163     return CompareStringA(LOCALE_SYSTEM_DEFAULT,0,str1,-1,str2,-1) - 2 ;
164 }
165
166
167 /***********************************************************************
168  *           lstrcmp32W   (KERNEL.603)
169  * FIXME : should call CompareString32W, when it is implemented.
170  *    This implementation is not "word sort", as it should.
171  */
172 INT WINAPI lstrcmpW( LPCWSTR str1, LPCWSTR str2 )
173 {
174     TRACE("%s and %s\n",
175                    debugstr_w (str1), debugstr_w (str2));
176     if (!str1 || !str2) {
177         SetLastError(ERROR_INVALID_PARAMETER);
178         return 0;
179     }
180     while (*str1 && (*str1 == *str2)) { str1++; str2++; }
181     return (INT)(*str1 - *str2);
182 }
183
184
185 /***********************************************************************
186  *           lstrcmpi16   (USER.471)
187  */
188 INT16 WINAPI lstrcmpi16( LPCSTR str1, LPCSTR str2 )
189 {
190     return (INT16)lstrcmpiA( str1, str2 );
191 }
192
193
194 /***********************************************************************
195  *           lstrcmpi32A   (KERNEL32.605)
196  */
197 INT WINAPI lstrcmpiA( LPCSTR str1, LPCSTR str2 )
198 {    TRACE("strcmpi %s and %s\n",
199                    debugstr_a (str1), debugstr_a (str2));
200     return CompareStringA(LOCALE_SYSTEM_DEFAULT,NORM_IGNORECASE,str1,-1,str2,-1)-2;
201 }
202
203
204 /***********************************************************************
205  *           lstrcmpi32W   (KERNEL32.606)
206  */
207 INT WINAPI lstrcmpiW( LPCWSTR str1, LPCWSTR str2 )
208 {
209     INT res;
210
211 #if 0
212     /* Too much!  (From registry loading.)  */
213     TRACE("strcmpi %s and %s\n",
214                    debugstr_w (str1), debugstr_w (str2));
215 #endif
216     if (!str1 || !str2) {
217         SetLastError(ERROR_INVALID_PARAMETER);
218         return 0;
219     }
220     while (*str1)
221     {
222         if ((*str1<0x100 ) && (*str2<0x100)) {
223             if ((res = toupper(*str1) - toupper(*str2)) != 0) return res;
224         } else {
225             if ((res = towupper(*str1) - towupper(*str2)) != 0) return res;
226         }
227         str1++;
228         str2++;
229     }
230     return towupper(*str1) - towupper(*str2);
231 }
232
233
234 /***********************************************************************
235  *           lstrcpy16   (KERNEL.88)
236  */
237 SEGPTR WINAPI lstrcpy16( SEGPTR dst, LPCSTR src )
238 {
239     /* this is how Windows does it */
240     memmove( (LPSTR)PTR_SEG_TO_LIN(dst), src, strlen(src)+1 );
241     return dst;
242 }
243
244
245 /***********************************************************************
246  *           lstrcpyA   (KERNEL32.608)
247  */
248 LPSTR WINAPI lstrcpyA( LPSTR dst, LPCSTR src )
249 {
250     __TRY
251     {
252         /* this is how Windows does it */
253         memmove( dst, src, strlen(src)+1 );
254     }
255     __EXCEPT(page_fault)
256     {
257         SetLastError( ERROR_INVALID_PARAMETER );
258         return NULL;
259     }
260     __ENDTRY
261     return dst;
262 }
263
264
265 /***********************************************************************
266  *           lstrcpyW   (KERNEL32.609)
267  */
268 LPWSTR WINAPI lstrcpyW( LPWSTR dst, LPCWSTR src )
269 {
270     __TRY
271     {
272         CRTDLL_wcscpy( dst, src );
273     }
274     __EXCEPT(page_fault)
275     {
276         SetLastError( ERROR_INVALID_PARAMETER );
277         return NULL;
278     }
279     __ENDTRY
280     return dst;
281 }
282
283
284 /***********************************************************************
285  *           lstrcpyn16   (KERNEL.353)
286  */
287 SEGPTR WINAPI lstrcpyn16( SEGPTR dst, LPCSTR src, INT16 n )
288 {
289     lstrcpynA( (LPSTR)PTR_SEG_TO_LIN(dst), src, n );
290     return dst;
291 }
292
293
294 /***********************************************************************
295  *           lstrcpyn32A   (KERNEL32.611)
296  * Note: this function differs from the UNIX strncpy, it _always_ writes
297  * a terminating \0
298  */
299 LPSTR WINAPI lstrcpynA( LPSTR dst, LPCSTR src, INT n )
300 {
301     LPSTR p = dst;
302     TRACE("(%p, %s, %i)\n", dst, debugstr_an(src,n), n);
303     /* In real windows the whole function is protected by an exception handler
304      * that returns ERROR_INVALID_PARAMETER on faulty parameters
305      * We currently just check for NULL.
306      */
307     if (!dst || !src) {
308         SetLastError(ERROR_INVALID_PARAMETER);
309         return 0;
310     }
311     while ((n-- > 1) && *src) *p++ = *src++;
312     if (n >= 0) *p = 0;
313     return dst;
314 }
315
316
317 /***********************************************************************
318  *           lstrcpyn32W   (KERNEL32.612)
319  * Note: this function differs from the UNIX strncpy, it _always_ writes
320  * a terminating \0
321  */
322 LPWSTR WINAPI lstrcpynW( LPWSTR dst, LPCWSTR src, INT n )
323 {
324     LPWSTR p = dst;
325     TRACE("(%p, %s, %i)\n", dst,  debugstr_wn(src,n), n);
326     /* In real windows the whole function is protected by an exception handler
327      * that returns ERROR_INVALID_PARAMETER on faulty parameters
328      * We currently just check for NULL.
329      */
330     if (!dst || !src) {
331         SetLastError(ERROR_INVALID_PARAMETER);
332         return 0;
333     }
334     while ((n-- > 1) && *src) *p++ = *src++;
335     if (n >= 0) *p = 0;
336     return dst;
337 }
338
339
340 /***********************************************************************
341  *           lstrlen16   (KERNEL.90)
342  */
343 INT16 WINAPI lstrlen16( LPCSTR str )
344 {
345     return (INT16)lstrlenA( str );
346 }
347
348
349 /***********************************************************************
350  *           lstrlenA   (KERNEL32.614)
351  */
352 INT WINAPI lstrlenA( LPCSTR str )
353 {
354     INT ret;
355     __TRY
356     {
357         ret = strlen(str);
358     }
359     __EXCEPT(page_fault)
360     {
361         SetLastError( ERROR_INVALID_PARAMETER );
362         return 0;
363     }
364     __ENDTRY
365     return ret;
366 }
367
368
369 /***********************************************************************
370  *           lstrlenW   (KERNEL32.615)
371  */
372 INT WINAPI lstrlenW( LPCWSTR str )
373 {
374     INT ret;
375     __TRY
376     {
377         ret = CRTDLL_wcslen(str);
378     }
379     __EXCEPT(page_fault)
380     {
381         SetLastError( ERROR_INVALID_PARAMETER );
382         return 0;
383     }
384     __ENDTRY
385     return ret;
386 }
387
388
389 /***********************************************************************
390  *           lstrcpyAtoW   (Not a Windows API)
391  */
392 LPWSTR WINAPI lstrcpyAtoW( LPWSTR dst, LPCSTR src )
393 {
394     register LPWSTR p = dst;
395
396     TRACE("(%p, %s)\n", dst, debugstr_a(src));
397
398     while ((*p++ = (WCHAR)(unsigned char)*src++));
399     return dst;
400 }
401
402
403 /***********************************************************************
404  *           lstrcpyWtoA   (Not a Windows API)
405  */
406 LPSTR WINAPI lstrcpyWtoA( LPSTR dst, LPCWSTR src )
407 {
408     register LPSTR p = dst;
409
410     TRACE("(%p, %s)\n", dst, debugstr_w(src));
411
412     while ((*p++ = (CHAR)*src++));
413     return dst;
414 }
415
416
417 /***********************************************************************
418  *           lstrcpynAtoW   (Not a Windows API)
419  * Note: this function differs from the UNIX strncpy, it _always_ writes
420  * a terminating \0
421  */
422 LPWSTR WINAPI lstrcpynAtoW( LPWSTR dst, LPCSTR src, INT n )
423 {
424     LPWSTR p = dst;
425
426     TRACE("(%p, %s, %i)\n", dst, debugstr_an(src,n), n);
427
428     while ((n-- > 1) && *src) *p++ = (WCHAR)(unsigned char)*src++;
429     if (n >= 0) *p = 0;
430     return dst;
431 }
432
433
434 /***********************************************************************
435  *           lstrcpynWtoA   (Not a Windows API)
436  * Note: this function differs from the UNIX strncpy, it _always_ writes
437  * a terminating \0
438  *
439  * The terminating zero should be written at the end of the string, not
440  * the end of the buffer, as some programs specify the wrong size for 
441  * the buffer (eg. winnt's sol.exe)
442  */
443 LPSTR WINAPI lstrcpynWtoA( LPSTR dst, LPCWSTR src, INT n )
444 {
445     if (--n >= 0)
446     {
447         TRACE("(%p, %s, %i)\n", dst, debugstr_wn(src,n), n);
448         n = CRTDLL_wcstombs( dst, src, n );
449         if(n<0)
450                  n=0;
451         dst[n] = 0;
452     }
453     return dst;
454 }
455
456 /***********************************************************************
457  *           UnicodeToAnsi   (KERNEL.434)
458  */
459 INT16 WINAPI UnicodeToAnsi16( LPCWSTR src, LPSTR dst, INT16 codepage )
460 {
461     if ( codepage != -1 )
462         FIXME("codepage %d not supported\n", codepage );
463
464     lstrcpyWtoA( dst, src );
465
466     return (INT16)lstrlenA( dst );
467 }
468
469
470 /***********************************************************************
471  *           Copy   (GDI.250)
472  */
473 void WINAPI Copy16( LPVOID src, LPVOID dst, WORD size )
474 {
475     memcpy( dst, src, size );
476 }
477
478
479 /***********************************************************************
480  *           RtlFillMemory   (KERNEL32.441)
481  */
482 VOID WINAPI RtlFillMemory( LPVOID ptr, UINT len, UINT fill )
483 {
484     memset( ptr, fill, len );
485 }
486
487
488 /***********************************************************************
489  *           RtlMoveMemory   (KERNEL32.442)
490  */
491 VOID WINAPI RtlMoveMemory( LPVOID dst, LPCVOID src, UINT len )
492 {
493     memmove( dst, src, len );
494 }
495
496
497 /***********************************************************************
498  *           RtlZeroMemory   (KERNEL32.444)
499  */
500 VOID WINAPI RtlZeroMemory( LPVOID ptr, UINT len )
501 {
502     memset( ptr, 0, len );
503 }
504
505
506 /***********************************************************************
507  *           AnsiToOem16   (KEYBOARD.5)
508  */
509 INT16 WINAPI AnsiToOem16( LPCSTR s, LPSTR d )
510 {
511     CharToOemA( s, d );
512     return -1;
513 }
514
515
516 /***********************************************************************
517  *           OemToAnsi16   (KEYBOARD.6)
518  */
519 INT16 WINAPI OemToAnsi16( LPCSTR s, LPSTR d )
520 {
521     OemToCharA( s, d );
522     return -1;
523 }
524
525
526 /***********************************************************************
527  *           AnsiToOemBuff16   (KEYBOARD.134)
528  */
529 void WINAPI AnsiToOemBuff16( LPCSTR s, LPSTR d, UINT16 len )
530 {
531     if (len != 0) CharToOemBuffA( s, d, len );
532 }
533
534
535 /***********************************************************************
536  *           OemToAnsiBuff16   (KEYBOARD.135)
537  */
538 void WINAPI OemToAnsiBuff16( LPCSTR s, LPSTR d, UINT16 len )
539 {
540     if (len != 0) OemToCharBuffA( s, d, len );
541 }
542
543
544 /***********************************************************************
545  *           CharToOem32A   (USER32.37)
546  */
547 BOOL WINAPI CharToOemA( LPCSTR s, LPSTR d )
548 {
549     LPSTR oldd = d;
550     if (!s || !d) return TRUE;
551     TRACE("CharToOem %s\n", debugstr_a (s));
552     while ((*d++ = ANSI_TO_OEM(*s++)));
553     TRACE("       to %s\n", debugstr_a (oldd));
554     return TRUE;
555 }
556
557
558 /***********************************************************************
559  *           CharToOemBuff32A   (USER32.38)
560  */
561 BOOL WINAPI CharToOemBuffA( LPCSTR s, LPSTR d, DWORD len )
562 {
563     while (len--) *d++ = ANSI_TO_OEM(*s++);
564     return TRUE;
565 }
566
567
568 /***********************************************************************
569  *           CharToOemBuff32W   (USER32.39)
570  */
571 BOOL WINAPI CharToOemBuffW( LPCWSTR s, LPSTR d, DWORD len )
572 {
573     while (len--) *d++ = ANSI_TO_OEM(*s++);
574     return TRUE;
575 }
576
577
578 /***********************************************************************
579  *           CharToOem32W   (USER32.40)
580  */
581 BOOL WINAPI CharToOemW( LPCWSTR s, LPSTR d )
582 {
583     LPSTR oldd = d;
584     if (!s || !d) return TRUE;
585     TRACE("CharToOem %s\n", debugstr_w (s));
586     while ((*d++ = ANSI_TO_OEM(*s++)));
587     TRACE("       to %s\n", debugstr_a (oldd));
588     return TRUE;
589 }
590
591
592 /***********************************************************************
593  *           OemToChar32A   (USER32.402)
594  */
595 BOOL WINAPI OemToCharA( LPCSTR s, LPSTR d )
596 {
597     LPSTR oldd = d;
598     TRACE("OemToChar %s\n", debugstr_a (s));
599     while ((*d++ = OEM_TO_ANSI(*s++)));
600     TRACE("       to %s\n", debugstr_a (oldd));
601     return TRUE;
602 }
603
604
605 /***********************************************************************
606  *           OemToCharBuff32A   (USER32.403)
607  */
608 BOOL WINAPI OemToCharBuffA( LPCSTR s, LPSTR d, DWORD len )
609 {
610     TRACE("OemToCharBuff %s\n", debugstr_an (s, len));
611     while (len--) *d++ = OEM_TO_ANSI(*s++);
612     return TRUE;
613 }
614
615
616 /***********************************************************************
617  *           OemToCharBuff32W   (USER32.404)
618  */
619 BOOL WINAPI OemToCharBuffW( LPCSTR s, LPWSTR d, DWORD len )
620 {
621     TRACE("OemToCharBuff %s\n", debugstr_an (s, len));
622     while (len--) *d++ = (WCHAR)OEM_TO_ANSI(*s++);
623     return TRUE;
624 }
625
626
627 /***********************************************************************
628  *           OemToChar32W   (USER32.405)
629  */
630 BOOL WINAPI OemToCharW( LPCSTR s, LPWSTR d )
631 {
632     while ((*d++ = (WCHAR)OEM_TO_ANSI(*s++)));
633     return TRUE;
634 }
635
636 /***********************************************************************
637  *           lstrrchr   (Not a Windows API)
638  *
639  * This is the implementation meant to be invoked from within
640  * COMCTL32_StrRChrA and shell32(TODO)...
641  *
642  * Return a pointer to the last occurence of wMatch in lpStart
643  * not looking further than lpEnd...
644  */
645 LPSTR WINAPI lstrrchr( LPCSTR lpStart, LPCSTR lpEnd, WORD wMatch )
646 {
647   LPCSTR lpGotIt = NULL;
648
649   TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
650
651   if (!lpEnd) lpEnd = lpStart + strlen(lpStart);
652
653   for(; lpStart < lpEnd; lpStart = CharNextA(lpStart)) 
654     if (!ChrCmpA( GET_WORD(lpStart), wMatch)) 
655       lpGotIt = lpStart;
656     
657   return ((LPSTR)lpGotIt);
658 }
659
660 /***********************************************************************
661  *           ChrCmpW   
662  * This fuction returns FALSE if both words match, TRUE otherwise...
663  */
664 static BOOL ChrCmpW( WORD word1, WORD word2) {
665   return (word1 != word2);
666 }
667
668 /***********************************************************************
669  *           lstrrchrw    (Not a Windows API)
670  *
671  * This is the implementation meant to be invoked form within
672  * COMCTL32_StrRChrW and shell32(TODO)...
673  *
674  * Return a pointer to the last occurence of wMatch in lpStart
675  * not looking further than lpEnd...
676  */  
677 LPWSTR WINAPI lstrrchrw( LPCWSTR lpStart, LPCWSTR lpEnd, WORD wMatch )
678 {
679   LPCWSTR lpGotIt = NULL;
680
681   TRACE("(%p, %p, %x)\n", lpStart, lpEnd, wMatch);
682   if (!lpEnd) lpEnd = lpStart + lstrlenW(lpStart);
683
684   for(; lpStart < lpEnd; lpStart = CharNextW(lpStart)) 
685     if (!ChrCmpW( GET_WORD(lpStart), wMatch)) 
686       lpGotIt = lpStart;
687     
688   return (LPWSTR)lpGotIt;
689 }
690
691 /***********************************************************************
692  *           ChrCmpA   
693  * This fuction returns FALSE if both words match, TRUE otherwise...
694  */
695 static BOOL ChrCmpA( WORD word1, WORD word2) {
696   if (LOBYTE(word1) == LOBYTE(word2)) {
697     if (IsDBCSLeadByte(LOBYTE(word1))) {
698       return (word1 != word2);
699     }
700     return FALSE;
701   }
702   return TRUE;
703 }