Release 980301
[wine/multimedia.git] / misc / lstr.c
blob252d081e39a68bf09e99f26f97c0c3e20ffdf04c
1 /*
2 * String functions
4 * Copyright 1993 Yngvi Sigurjonsson (yngvi@hafro.is)
5 * Copyright 1996 Marcus Meissner
6 */
8 #include <stdio.h>
9 #include <stdarg.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <ctype.h>
13 #include "config.h"
15 #ifdef HAVE_WCTYPE_H
16 # include <wctype.h>
17 #else
18 # define towlower(c) tolower(c)
19 # define towupper(c) toupper(c)
20 # define iswalnum(c) isalnum(c)
21 # define iswalpha(c) isalpha(c)
22 # define iswupper(c) isupper(c)
23 # define iswlower(c) islower(c)
24 #endif /* HAVE_WCTYPE_H */
27 #include "windows.h"
28 #include "winnt.h" /* HEAP_ macros */
29 #include "task.h"
30 #include "heap.h"
31 #include "ldt.h"
32 #include "stackframe.h"
33 #include "module.h"
34 #include "debug.h"
36 /* Funny to divide them between user and kernel. */
38 /* be careful: always use functions from wctype.h if character > 255 */
40 /***********************************************************************
41 * IsCharAlpha (USER.433)
43 BOOL16 WINAPI IsCharAlpha16(CHAR ch)
45 return isalpha(ch); /* This is probably not right for NLS */
48 /***********************************************************************
49 * IsCharAlphanumeric (USER.434)
51 BOOL16 WINAPI IsCharAlphaNumeric16(CHAR ch)
53 return isalnum(ch);
56 /***********************************************************************
57 * IsCharUpper (USER.435)
59 BOOL16 WINAPI IsCharUpper16(CHAR ch)
61 return isupper(ch);
64 /***********************************************************************
65 * IsCharLower (USER.436)
67 BOOL16 WINAPI IsCharLower16(CHAR ch)
69 return islower(ch);
72 /***********************************************************************
73 * AnsiUpper16 (USER.431)
75 SEGPTR WINAPI AnsiUpper16( SEGPTR strOrChar )
77 /* I am not sure if the locale stuff works with toupper, but then again
78 I am not sure if the Linux libc locale stuffs works at all */
80 /* uppercase only one char if strOrChar < 0x10000 */
81 if (HIWORD(strOrChar))
83 char *s;
84 for (s = PTR_SEG_TO_LIN(strOrChar); *s; s++) *s = toupper(*s);
85 return strOrChar;
87 else return toupper((char)strOrChar);
91 /***********************************************************************
92 * AnsiUpperBuff16 (USER.437)
94 UINT16 WINAPI AnsiUpperBuff16( LPSTR str, UINT16 len )
96 UINT32 count = len ? len : 65536;
97 for (; count; count--, str++) *str = toupper(*str);
98 return len;
101 /***********************************************************************
102 * AnsiLower16 (USER.432)
104 SEGPTR WINAPI AnsiLower16( SEGPTR strOrChar )
106 /* I am not sure if the locale stuff works with toupper, but then again
107 I am not sure if the Linux libc locale stuffs works at all */
109 /* lowercase only one char if strOrChar < 0x10000 */
110 if (HIWORD(strOrChar))
112 char *s;
113 for (s = PTR_SEG_TO_LIN( strOrChar ); *s; s++) *s = tolower( *s );
114 return strOrChar;
116 else return tolower((char)strOrChar);
120 /***********************************************************************
121 * AnsiLowerBuff16 (USER.438)
123 UINT16 WINAPI AnsiLowerBuff16( LPSTR str, UINT16 len )
125 UINT32 count = len ? len : 65536;
126 for (; count; count--, str++) *str = tolower(*str);
127 return len;
131 /***********************************************************************
132 * AnsiNext16 (USER.472)
134 SEGPTR WINAPI AnsiNext16(SEGPTR current)
136 return (*(char *)PTR_SEG_TO_LIN(current)) ? current + 1 : current;
140 /***********************************************************************
141 * AnsiPrev16 (USER.473)
143 SEGPTR WINAPI AnsiPrev16( SEGPTR start, SEGPTR current )
145 return (current == start) ? start : current - 1;
149 /***********************************************************************
150 * OutputDebugString16 (KERNEL.115)
152 void WINAPI OutputDebugString16( LPCSTR str )
154 char *module;
155 char *p, *buffer = HeapAlloc( GetProcessHeap(), 0, strlen(str)+2 );
156 /* Remove CRs */
157 for (p = buffer; *str; str++) if (*str != '\r') *p++ = *str;
158 *p = '\0';
159 if ((p > buffer) && (p[-1] == '\n')) p[1] = '\0'; /* Remove trailing \n */
160 module = MODULE_GetModuleName( GetCurrentTask() );
161 fprintf( stderr, "OutputDebugString: %s says '%s'\n",
162 module ? module : "???", buffer );
163 HeapFree( GetProcessHeap(), 0, buffer );
167 /***********************************************************************
168 * OutputDebugString32A (KERNEL32
170 void WINAPI OutputDebugString32A( LPCSTR str )
172 OutputDebugString16( str );
177 /***********************************************************************
178 * OutputDebugString32W (KERNEL32
180 void WINAPI OutputDebugString32W( LPCWSTR str )
182 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
183 OutputDebugString32A( p );
184 HeapFree( GetProcessHeap(), 0, p );
189 /***********************************************************************
190 * CharNext32A (USER32.28)
192 LPSTR WINAPI CharNext32A( LPCSTR ptr )
194 if (!*ptr) return (LPSTR)ptr;
195 if (IsDBCSLeadByte32( *ptr )) return (LPSTR)(ptr + 2);
196 return (LPSTR)(ptr + 1);
200 /***********************************************************************
201 * CharNextEx32A (USER32.29)
203 LPSTR WINAPI CharNextEx32A( WORD codepage, LPCSTR ptr, DWORD flags )
205 if (!*ptr) return (LPSTR)ptr;
206 if (IsDBCSLeadByteEx( codepage, *ptr )) return (LPSTR)(ptr + 2);
207 return (LPSTR)(ptr + 1);
211 /***********************************************************************
212 * CharNextExW (USER32.30)
214 LPWSTR WINAPI CharNextEx32W(WORD codepage,LPCWSTR x,DWORD flags)
216 /* FIXME: add DBCS / codepage stuff */
217 if (*x) return (LPWSTR)(x+1);
218 else return (LPWSTR)x;
221 /***********************************************************************
222 * CharNextW (USER32.31)
224 LPWSTR WINAPI CharNext32W(LPCWSTR x)
226 if (*x) return (LPWSTR)(x+1);
227 else return (LPWSTR)x;
230 /***********************************************************************
231 * CharPrev32A (USER32.32)
233 LPSTR WINAPI CharPrev32A( LPCSTR start, LPCSTR ptr )
235 while (*start && (start < ptr))
237 LPCSTR next = CharNext32A( start );
238 if (next >= ptr) break;
239 start = next;
241 return (LPSTR)start;
245 /***********************************************************************
246 * CharPrevEx32A (USER32.33)
248 LPSTR WINAPI CharPrevEx32A( WORD codepage, LPCSTR start, LPCSTR ptr, DWORD flags )
250 while (*start && (start < ptr))
252 LPCSTR next = CharNextEx32A( codepage, start, flags );
253 if (next > ptr) break;
254 start = next;
256 return (LPSTR)start;
260 /***********************************************************************
261 * CharPrevExW (USER32.34)
263 LPWSTR WINAPI CharPrevEx32W(WORD codepage,LPCWSTR start,LPCWSTR x,DWORD flags)
265 /* FIXME: add DBCS / codepage stuff */
266 if (x>start) return (LPWSTR)(x-1);
267 else return (LPWSTR)x;
270 /***********************************************************************
271 * CharPrevW (USER32.35)
273 LPWSTR WINAPI CharPrev32W(LPCWSTR start,LPCWSTR x)
275 if (x>start) return (LPWSTR)(x-1);
276 else return (LPWSTR)x;
279 /***********************************************************************
280 * CharLowerA (USER32.24)
281 * FIXME: handle current locale
283 LPSTR WINAPI CharLower32A(LPSTR x)
285 LPSTR s;
287 if (HIWORD(x))
289 s=x;
290 while (*s)
292 *s=tolower(*s);
293 s++;
295 return x;
297 else return (LPSTR)tolower((char)(int)x);
300 /***********************************************************************
301 * CharLowerBuffA (USER32.25)
302 * FIXME: handle current locale
304 DWORD WINAPI CharLowerBuff32A(LPSTR x,DWORD buflen)
306 DWORD done=0;
308 if (!x) return 0; /* YES */
309 while (*x && (buflen--))
311 *x=tolower(*x);
312 x++;
313 done++;
315 return done;
318 /***********************************************************************
319 * CharLowerBuffW (USER32.26)
320 * FIXME: handle current locale
322 DWORD WINAPI CharLowerBuff32W(LPWSTR x,DWORD buflen)
324 DWORD done=0;
326 if (!x) return 0; /* YES */
327 while (*x && (buflen--))
329 *x=towlower(*x);
330 x++;
331 done++;
333 return done;
336 /***********************************************************************
337 * CharLowerW (USER32.27)
338 * FIXME: handle current locale
340 LPWSTR WINAPI CharLower32W(LPWSTR x)
342 if (HIWORD(x))
344 LPWSTR s = x;
345 while (*s)
347 *s=towlower(*s);
348 s++;
350 return x;
352 else return (LPWSTR)towlower(LOWORD(x));
355 /***********************************************************************
356 * CharUpper32A (USER32.40)
357 * FIXME: handle current locale
359 LPSTR WINAPI CharUpper32A(LPSTR x)
361 if (HIWORD(x))
363 LPSTR s = x;
364 while (*s)
366 *s=toupper(*s);
367 s++;
369 return x;
371 return (LPSTR)toupper((char)(int)x);
374 /***********************************************************************
375 * CharUpperBuffA (USER32.41)
376 * FIXME: handle current locale
378 DWORD WINAPI CharUpperBuff32A(LPSTR x,DWORD buflen)
380 DWORD done=0;
382 if (!x) return 0; /* YES */
383 while (*x && (buflen--))
385 *x=toupper(*x);
386 x++;
387 done++;
389 return done;
392 /***********************************************************************
393 * CharUpperBuffW (USER32.42)
394 * FIXME: handle current locale
396 DWORD WINAPI CharUpperBuff32W(LPWSTR x,DWORD buflen)
398 DWORD done=0;
400 if (!x) return 0; /* YES */
401 while (*x && (buflen--))
403 *x=towupper(*x);
404 x++;
405 done++;
407 return done;
410 /***********************************************************************
411 * CharUpperW (USER32.43)
412 * FIXME: handle current locale
414 LPWSTR WINAPI CharUpper32W(LPWSTR x)
416 if (HIWORD(x))
418 LPWSTR s = x;
419 while (*s)
421 *s=towupper(*s);
422 s++;
424 return x;
426 else return (LPWSTR)towupper(LOWORD(x));
429 /***********************************************************************
430 * IsCharAlphaA (USER32.330)
431 * FIXME: handle current locale
433 BOOL32 WINAPI IsCharAlpha32A(CHAR x)
435 return isalpha(x);
438 /***********************************************************************
439 * IsCharAlphaNumericA (USER32.331)
440 * FIXME: handle current locale
442 BOOL32 WINAPI IsCharAlphaNumeric32A(CHAR x)
444 return isalnum(x);
447 /***********************************************************************
448 * IsCharAlphaNumericW (USER32.332)
449 * FIXME: handle current locale
451 BOOL32 WINAPI IsCharAlphaNumeric32W(WCHAR x)
453 return iswalnum(x);
456 /***********************************************************************
457 * IsCharAlphaW (USER32.333)
458 * FIXME: handle current locale
460 BOOL32 WINAPI IsCharAlpha32W(WCHAR x)
462 return iswalpha(x);
465 /***********************************************************************
466 * IsCharLower32A (USER32.334)
467 * FIXME: handle current locale
469 BOOL32 WINAPI IsCharLower32A(CHAR x)
471 return islower(x);
474 /***********************************************************************
475 * IsCharLower32W (USER32.335)
476 * FIXME: handle current locale
478 BOOL32 WINAPI IsCharLower32W(WCHAR x)
480 return iswlower(x);
483 /***********************************************************************
484 * IsCharUpper32A (USER32.336)
485 * FIXME: handle current locale
487 BOOL32 WINAPI IsCharUpper32A(CHAR x)
489 return isupper(x);
492 /***********************************************************************
493 * IsCharUpper32W (USER32.337)
494 * FIXME: handle current locale
496 BOOL32 WINAPI IsCharUpper32W(WCHAR x)
498 return iswupper(x);
501 /***********************************************************************
502 * FormatMessage32A (KERNEL32.138)
503 * FIXME: missing wrap,FROM_SYSTEM message-loading,
505 DWORD WINAPI FormatMessage32A(
506 DWORD dwFlags,
507 LPCVOID lpSource,
508 DWORD dwMessageId,
509 DWORD dwLanguageId,
510 LPSTR lpBuffer,
511 DWORD nSize,
512 LPDWORD args /* va_list *args */
514 LPSTR target,t;
515 DWORD talloced;
516 LPSTR from,f;
517 DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
518 DWORD nolinefeed = 0;
520 dprintf_info(resource,
521 "FormatMessage32A(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
522 dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args
524 if (width)
525 fprintf(stdnimp," - line wrapping not supported.\n");
526 from = NULL;
527 if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
528 from = HEAP_strdupA( GetProcessHeap(), 0, (LPSTR)lpSource);
529 if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) {
530 from = HeapAlloc( GetProcessHeap(),0,200 );
531 sprintf(from,"Systemmessage, messageid = 0x%08lx\n",dwMessageId);
533 if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) {
534 INT32 bufsize;
536 dwMessageId &= 0xFFFF;
537 bufsize=LoadMessage32A((HMODULE32)lpSource,dwMessageId,dwLanguageId,NULL,100);
538 if (bufsize) {
539 from = HeapAlloc( GetProcessHeap(), 0, bufsize + 1 );
540 LoadMessage32A((HMODULE32)lpSource,dwMessageId,dwLanguageId,from,bufsize+1);
543 target = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100);
544 t = target;
545 talloced= 100;
547 #define ADD_TO_T(c) \
548 *t++=c;\
549 if (t-target == talloced) {\
550 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
551 t = target+talloced;\
552 talloced*=2;\
555 if (from) {
556 f=from;
557 while (*f) {
558 if (*f=='%') {
559 int insertnr;
560 char *fmtstr,*sprintfbuf,*x,*lastf;
561 DWORD *argliststart;
563 fmtstr = NULL;
564 lastf = f;
565 f++;
566 if (!*f) {
567 ADD_TO_T('%');
568 continue;
570 switch (*f) {
571 case '1':case '2':case '3':case '4':case '5':
572 case '6':case '7':case '8':case '9':
573 insertnr=*f-'0';
574 switch (f[1]) {
575 case '0':case '1':case '2':case '3':
576 case '4':case '5':case '6':case '7':
577 case '8':case '9':
578 f++;
579 insertnr=insertnr*10+*f-'0';
580 f++;
581 break;
582 default:
583 f++;
584 break;
586 if (*f=='!') {
587 f++;
588 if (NULL!=(x=strchr(f,'!'))) {
589 *x='\0';
590 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f)+2);
591 sprintf(fmtstr,"%%%s",f);
592 f=x+1;
593 } else {
594 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f));
595 sprintf(fmtstr,"%%%s",f);
596 f+=strlen(f); /*at \0*/
598 } else
599 fmtstr=HEAP_strdupA(GetProcessHeap(),0,"%s");
600 if (args) {
601 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
602 argliststart=args+insertnr-1;
603 else
604 argliststart=(*(DWORD**)args)+insertnr-1;
606 if (fmtstr[strlen(fmtstr)]=='s')
607 sprintfbuf=HeapAlloc(GetProcessHeap(),0,strlen((LPSTR)argliststart[0])+1);
608 else
609 sprintfbuf=HeapAlloc(GetProcessHeap(),0,100);
611 /* CMF - This makes a BIG assumption about va_list */
612 vsprintf(sprintfbuf, fmtstr, (va_list) argliststart);
613 x=sprintfbuf;
614 while (*x) {
615 ADD_TO_T(*x++);
617 HeapFree(GetProcessHeap(),0,sprintfbuf);
618 } else {
619 /* NULL args - copy formatstr
620 * (probably wrong)
622 while (lastf<f) {
623 ADD_TO_T(*lastf++);
626 HeapFree(GetProcessHeap(),0,fmtstr);
627 break;
628 case 'n':
629 /* FIXME: perhaps add \r too? */
630 ADD_TO_T('\n');
631 f++;
632 break;
633 case '0':
634 nolinefeed=1;
635 f++;
636 break;
637 default:ADD_TO_T(*f++)
638 break;
641 } else {
642 ADD_TO_T(*f++)
645 *t='\0';
647 if (!nolinefeed && t[-1]!='\n')
648 ADD_TO_T('\n');
649 talloced = strlen(target)+1;
650 if (nSize && talloced<nSize) {
651 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
653 if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
654 /* nSize is the MINIMUM size */
655 *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc32(GMEM_ZEROINIT,talloced);
656 memcpy(*(LPSTR*)lpBuffer,target,talloced);
657 } else
658 strncpy(lpBuffer,target,nSize);
659 HeapFree(GetProcessHeap(),0,target);
660 if (from) HeapFree(GetProcessHeap(),0,from);
661 return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
662 strlen(*(LPSTR*)lpBuffer):
663 strlen(lpBuffer);
665 #undef ADD_TO_T
668 /***********************************************************************
669 * FormatMessage32W (KERNEL32.138)
671 DWORD WINAPI FormatMessage32W(
672 DWORD dwFlags,
673 LPCVOID lpSource,
674 DWORD dwMessageId,
675 DWORD dwLanguageId,
676 LPWSTR lpBuffer,
677 DWORD nSize,
678 LPDWORD args /* va_list *args */
680 LPSTR target,t;
681 DWORD talloced;
682 LPSTR from,f;
683 DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
684 DWORD nolinefeed = 0;
686 dprintf_info(resource,
687 "FormatMessage32A(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
688 dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args
690 if (width)
691 fprintf(stdnimp," - line wrapping not supported.\n");
692 from = NULL;
693 if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
694 from = HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)lpSource);
695 if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) {
696 /* gather information from system message tables ... */
697 from = HeapAlloc( GetProcessHeap(),0,200 );
698 sprintf(from,"Systemmessage, messageid = 0x%08lx\n",dwMessageId);
700 if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) {
701 INT32 bufsize;
703 dwMessageId &= 0xFFFF;
704 bufsize=LoadMessage32A((HMODULE32)lpSource,dwMessageId,dwLanguageId,NULL,100);
705 if (bufsize)
707 from = HeapAlloc( GetProcessHeap(), 0, bufsize + 1 );
708 LoadMessage32A((HMODULE32)lpSource,dwMessageId,dwLanguageId,from,bufsize+1);
711 target = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100 );
712 t = target;
713 talloced= 100;
715 #define ADD_TO_T(c) \
716 *t++=c;\
717 if (t-target == talloced) {\
718 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
719 t = target+talloced;\
720 talloced*=2;\
723 if (from) {
724 f=from;
725 while (*f) {
726 if (*f=='%') {
727 int insertnr;
728 char *fmtstr,*sprintfbuf,*x;
729 DWORD *argliststart;
731 fmtstr = NULL;
732 f++;
733 if (!*f) {
734 ADD_TO_T('%');
735 continue;
737 switch (*f) {
738 case '1':case '2':case '3':case '4':case '5':
739 case '6':case '7':case '8':case '9':
740 insertnr=*f-'0';
741 switch (f[1]) {
742 case '0':case '1':case '2':case '3':
743 case '4':case '5':case '6':case '7':
744 case '8':case '9':
745 f++;
746 insertnr=insertnr*10+*f-'0';
747 f++;
748 break;
749 default:
750 f++;
751 break;
753 if (*f=='!') {
754 f++;
755 if (NULL!=(x=strchr(f,'!')))
757 *x='\0';
758 fmtstr=HeapAlloc( GetProcessHeap(), 0, strlen(f)+2);
759 sprintf(fmtstr,"%%%s",f);
760 f=x+1;
761 } else {
762 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f));
763 sprintf(fmtstr,"%%%s",f);
764 f+=strlen(f); /*at \0*/
766 } else
767 fmtstr=HEAP_strdupA( GetProcessHeap(),0,"%s");
768 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
769 argliststart=args+insertnr-1;
770 else
771 argliststart=(*(DWORD**)args)+insertnr-1;
773 if (fmtstr[strlen(fmtstr)]=='s') {
774 DWORD xarr[3];
776 xarr[0]=(DWORD)HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)(*(argliststart+0)));
777 /* possible invalid pointers */
778 xarr[1]=*(argliststart+1);
779 xarr[2]=*(argliststart+2);
780 sprintfbuf=HeapAlloc(GetProcessHeap(),0,lstrlen32W((LPWSTR)argliststart[0])*2+1);
782 /* CMF - This makes a BIG assumption about va_list */
783 vsprintf(sprintfbuf, fmtstr, (va_list) xarr);
784 } else {
785 sprintfbuf=HeapAlloc(GetProcessHeap(),0,100);
787 /* CMF - This makes a BIG assumption about va_list */
788 vsprintf(sprintfbuf, fmtstr, (va_list) argliststart);
790 x=sprintfbuf;
791 while (*x) {
792 ADD_TO_T(*x++);
794 HeapFree(GetProcessHeap(),0,sprintfbuf);
795 HeapFree(GetProcessHeap(),0,fmtstr);
796 break;
797 case 'n':
798 /* FIXME: perhaps add \r too? */
799 ADD_TO_T('\n');
800 f++;
801 break;
802 case '0':
803 nolinefeed=1;
804 f++;
805 break;
806 default:ADD_TO_T(*f++)
807 break;
810 } else {
811 ADD_TO_T(*f++)
814 *t='\0';
816 if (!nolinefeed && t[-1]!='\n')
817 ADD_TO_T('\n');
818 talloced = strlen(target)+1;
819 if (nSize && talloced<nSize)
820 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
821 if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
822 /* nSize is the MINIMUM size */
823 *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc32(GMEM_ZEROINIT,talloced*2+2);
824 lstrcpynAtoW(*(LPWSTR*)lpBuffer,target,talloced);
825 } else
826 lstrcpynAtoW(lpBuffer,target,nSize);
827 HeapFree(GetProcessHeap(),0,target);
828 if (from) HeapFree(GetProcessHeap(),0,from);
829 return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
830 lstrlen32W(*(LPWSTR*)lpBuffer):
831 lstrlen32W(lpBuffer);
833 #undef ADD_TO_T