Release 970804
[wine/multimedia.git] / misc / lstr.c
blob7228e67deb71a23a984f89c97e593a385cf47f5d
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>
14 #include "windows.h"
15 #include "winnt.h" /* HEAP_ macros */
16 #include "heap.h"
17 #include "ldt.h"
18 #include "module.h"
19 #include "stddebug.h"
20 #include "debug.h"
22 #define ToUpper(c) toupper(c)
23 #define ToLower(c) tolower(c)
26 /* Funny to divide them between user and kernel. */
28 /* IsCharAlpha USER 433 */
29 BOOL16 IsCharAlpha16(CHAR ch)
31 return isalpha(ch); /* This is probably not right for NLS */
34 /* IsCharAlphanumeric USER 434 */
35 BOOL16 IsCharAlphanumeric16(CHAR ch)
37 return isalnum(ch);
40 /* IsCharUpper USER 435 */
41 BOOL16 IsCharUpper16(CHAR ch)
43 return isupper(ch);
46 /* IsCharLower USER 436 */
47 BOOL16 IsCharLower16(CHAR ch)
49 return islower(ch);
52 /***********************************************************************
53 * AnsiUpper16 (USER.431)
55 SEGPTR AnsiUpper16( SEGPTR strOrChar )
57 /* I am not sure if the locale stuff works with toupper, but then again
58 I am not sure if the Linux libc locale stuffs works at all */
60 /* uppercase only one char if strOrChar < 0x10000 */
61 if (HIWORD(strOrChar))
63 char *s;
64 for (s = PTR_SEG_TO_LIN(strOrChar); *s; s++) *s = toupper(*s);
65 return strOrChar;
67 else return (SEGPTR)ToUpper( (int)strOrChar );
71 /***********************************************************************
72 * AnsiUpperBuff16 (USER.437)
74 UINT16 AnsiUpperBuff16( LPSTR str, UINT16 len )
76 UINT32 count = len ? len : 65536;
77 for (; count; count--, str++) *str = toupper(*str);
78 return len;
81 /***********************************************************************
82 * AnsiLower16 (USER.432)
84 SEGPTR AnsiLower16( SEGPTR strOrChar )
86 /* I am not sure if the locale stuff works with toupper, but then again
87 I am not sure if the Linux libc locale stuffs works at all */
89 /* lowercase only one char if strOrChar < 0x10000 */
90 if (HIWORD(strOrChar))
92 char *s;
93 for (s = PTR_SEG_TO_LIN( strOrChar ); *s; s++) *s = tolower( *s );
94 return strOrChar;
96 else return (SEGPTR)tolower( (int)strOrChar );
100 /***********************************************************************
101 * AnsiLowerBuff16 (USER.438)
103 UINT16 AnsiLowerBuff16( LPSTR str, UINT16 len )
105 UINT32 count = len ? len : 65536;
106 for (; count; count--, str++) *str = tolower(*str);
107 return len;
111 /***********************************************************************
112 * AnsiNext16 (USER.472)
114 SEGPTR AnsiNext16(SEGPTR current)
116 return (*(char *)PTR_SEG_TO_LIN(current)) ? current + 1 : current;
120 /***********************************************************************
121 * AnsiPrev16 (USER.473)
123 SEGPTR AnsiPrev16( SEGPTR start, SEGPTR current )
125 return (current == start) ? start : current - 1;
129 /***********************************************************************
130 * OutputDebugString16 (KERNEL.115)
132 void OutputDebugString16( LPCSTR str )
134 char *module;
135 char *p, *buffer = HeapAlloc( GetProcessHeap(), 0, strlen(str)+1 );
136 /* Remove CRs */
137 for (p = buffer; *str; str++) if (*str != '\r') *p++ = *str;
138 *p = '\0';
139 if ((p > buffer) && (p[-1] == '\n')) p[1] = '\0'; /* Remove trailing \n */
140 module = MODULE_GetModuleName( GetExePtr(GetCurrentTask()) );
141 fprintf( stderr, "OutputDebugString: %s says '%s'\n",
142 module ? module : "???", buffer );
143 HeapFree( GetProcessHeap(), 0, buffer );
147 /***********************************************************************
148 * OutputDebugString32A (KERNEL32
150 void OutputDebugString32A( LPCSTR str )
152 OutputDebugString16( str );
157 /***********************************************************************
158 * OutputDebugString32W (KERNEL32
160 void OutputDebugString32W( LPCWSTR str )
162 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
163 OutputDebugString32A( p );
164 HeapFree( GetProcessHeap(), 0, p );
169 /***********************************************************************
170 * CharNext32A (USER32.28)
172 LPSTR CharNext32A( LPCSTR ptr )
174 if (!*ptr) return (LPSTR)ptr;
175 if (IsDBCSLeadByte32( *ptr )) return (LPSTR)(ptr + 2);
176 return (LPSTR)(ptr + 1);
180 /***********************************************************************
181 * CharNextEx32A (USER32.29)
183 LPSTR CharNextEx32A( WORD codepage, LPCSTR ptr, DWORD flags )
185 if (!*ptr) return (LPSTR)ptr;
186 if (IsDBCSLeadByteEx( codepage, *ptr )) return (LPSTR)(ptr + 2);
187 return (LPSTR)(ptr + 1);
191 /***********************************************************************
192 * CharNextExW (USER32.30)
194 LPWSTR CharNextEx32W(WORD codepage,LPCWSTR x,DWORD flags)
196 /* FIXME: add DBCS / codepage stuff */
197 if (*x) return (LPWSTR)(x+1);
198 else return (LPWSTR)x;
201 /***********************************************************************
202 * CharNextW (USER32.31)
204 LPWSTR CharNext32W(LPCWSTR x)
206 if (*x) return (LPWSTR)(x+1);
207 else return (LPWSTR)x;
210 /***********************************************************************
211 * CharPrev32A (USER32.32)
213 LPSTR CharPrev32A( LPCSTR start, LPCSTR ptr )
215 while (*start && (start < ptr))
217 LPCSTR next = CharNext32A( start );
218 if (next >= ptr) break;
219 start = next;
221 return (LPSTR)start;
225 /***********************************************************************
226 * CharPrevEx32A (USER32.33)
228 LPSTR CharPrevEx32A( WORD codepage, LPCSTR start, LPCSTR ptr, DWORD flags )
230 while (*start && (start < ptr))
232 LPCSTR next = CharNextEx32A( codepage, start, flags );
233 if (next > ptr) break;
234 start = next;
236 return (LPSTR)start;
240 /***********************************************************************
241 * CharPrevExW (USER32.34)
243 LPWSTR CharPrevEx32W(WORD codepage,LPCWSTR start,LPCWSTR x,DWORD flags)
245 /* FIXME: add DBCS / codepage stuff */
246 if (x>start) return (LPWSTR)(x-1);
247 else return (LPWSTR)x;
250 /***********************************************************************
251 * CharPrevW (USER32.35)
253 LPWSTR CharPrev32W(LPCWSTR start,LPCWSTR x)
255 if (x>start) return (LPWSTR)(x-1);
256 else return (LPWSTR)x;
259 /***********************************************************************
260 * CharLowerA (USER32.24)
261 * FIXME: handle current locale
263 LPSTR CharLower32A(LPSTR x)
265 LPSTR s;
267 if (HIWORD(x))
269 s=x;
270 while (*s)
272 *s=tolower(*s);
273 s++;
275 return x;
277 else return (LPSTR)tolower(LOWORD(x));
280 /***********************************************************************
281 * CharLowerBuffA (USER32.25)
282 * FIXME: handle current locale
284 DWORD CharLowerBuff32A(LPSTR x,DWORD buflen)
286 DWORD done=0;
288 while (*x && (buflen--))
290 *x=tolower(*x);
291 x++;
292 done++;
294 return done;
297 /***********************************************************************
298 * CharLowerBuffW (USER32.26)
299 * FIXME: handle current locale
301 DWORD CharLowerBuff32W(LPWSTR x,DWORD buflen)
303 DWORD done=0;
305 while (*x && (buflen--))
307 *x=tolower(*x);
308 x++;
309 done++;
311 return done;
314 /***********************************************************************
315 * CharLowerW (USER32.27)
316 * FIXME: handle current locale
318 LPWSTR CharLower32W(LPWSTR x)
320 if (HIWORD(x))
322 LPWSTR s = x;
323 while (*s)
325 *s=tolower(*s);
326 s++;
328 return x;
330 else return (LPWSTR)tolower(LOWORD(x));
333 /***********************************************************************
334 * CharUpper32A (USER32.40)
335 * FIXME: handle current locale
337 LPSTR CharUpper32A(LPSTR x)
339 if (HIWORD(x))
341 LPSTR s = x;
342 while (*s)
344 *s=toupper(*s);
345 s++;
347 return x;
349 else return (LPSTR)toupper(LOWORD(x));
352 /***********************************************************************
353 * CharUpperBuffA (USER32.41)
354 * FIXME: handle current locale
356 DWORD CharUpperBuff32A(LPSTR x,DWORD buflen)
358 DWORD done=0;
360 while (*x && (buflen--))
362 *x=toupper(*x);
363 x++;
364 done++;
366 return done;
369 /***********************************************************************
370 * CharUpperBuffW (USER32.42)
371 * FIXME: handle current locale
373 DWORD CharUpperBuff32W(LPWSTR x,DWORD buflen)
375 DWORD done=0;
377 while (*x && (buflen--))
379 *x=toupper(*x);
380 x++;
381 done++;
383 return done;
386 /***********************************************************************
387 * CharUpperW (USER32.43)
388 * FIXME: handle current locale
390 LPWSTR CharUpper32W(LPWSTR x)
392 if (HIWORD(x))
394 LPWSTR s = x;
395 while (*s)
397 *s=toupper(*s);
398 s++;
400 return x;
402 else return (LPWSTR)toupper(LOWORD(x));
405 /***********************************************************************
406 * IsCharAlphaA (USER32.330)
407 * FIXME: handle current locale
409 BOOL32 IsCharAlpha32A(CHAR x)
411 return isalpha(x);
414 /***********************************************************************
415 * IsCharAlphaNumericA (USER32.331)
416 * FIXME: handle current locale
418 BOOL32 IsCharAlphaNumeric32A(CHAR x)
420 return isalnum(x);
423 /***********************************************************************
424 * IsCharAlphaNumericW (USER32.332)
425 * FIXME: handle current locale
427 BOOL32 IsCharAlphaNumeric32W(WCHAR x)
429 return isalnum(x);
432 /***********************************************************************
433 * IsCharAlphaW (USER32.333)
434 * FIXME: handle current locale
436 BOOL32 IsCharAlpha32W(WCHAR x)
438 return isalpha(x);
441 /***********************************************************************
442 * IsCharLower32A (USER32.334)
443 * FIXME: handle current locale
445 BOOL32 IsCharLower32A(CHAR x)
447 return islower(x);
450 /***********************************************************************
451 * IsCharLower32W (USER32.335)
452 * FIXME: handle current locale
454 BOOL32 IsCharLower32W(WCHAR x)
456 return islower(x);
459 /***********************************************************************
460 * IsCharUpper32A (USER32.336)
461 * FIXME: handle current locale
463 BOOL32 IsCharUpper32A(CHAR x)
465 return isupper(x);
468 /***********************************************************************
469 * IsCharUpper32W (USER32.337)
470 * FIXME: handle current locale
472 BOOL32 IsCharUpper32W(WCHAR x)
474 return isupper(x);
477 /***********************************************************************
478 * FormatMessageA (KERNEL32.138) Library Version
479 * FIXME: missing wrap,FROM_SYSTEM message-loading,
481 DWORD
482 FormatMessage32A(
483 DWORD dwFlags,
484 LPCVOID lpSource,
485 DWORD dwMessageId,
486 DWORD dwLanguageId,
487 LPSTR lpBuffer,
488 DWORD nSize,
489 LPDWORD args /* va_list *args */
491 LPSTR target,t;
492 DWORD talloced;
493 LPSTR from,f;
494 DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
495 DWORD nolinefeed = 0;
497 dprintf_resource(stddeb,
498 "FormatMessage32A(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
499 dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args
501 if (width)
502 fprintf(stdnimp," - line wrapping not supported.\n");
503 from = NULL;
504 if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
505 from = HEAP_strdupA( GetProcessHeap(), 0, (LPSTR)lpSource);
506 if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) {
507 from = HeapAlloc( GetProcessHeap(),0,200 );
508 sprintf(from,"Systemmessage, messageid = 0x%08lx\n",dwMessageId);
510 if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) {
511 INT32 bufsize;
513 dwMessageId &= 0xFFFF;
514 bufsize=LoadMessage32A(0,dwMessageId,dwLanguageId,NULL,100);
515 if (bufsize) {
516 from = HeapAlloc( GetProcessHeap(), 0, bufsize + 1 );
517 LoadMessage32A(0,dwMessageId,dwLanguageId,from,bufsize+1);
520 target = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100);
521 t = target;
522 talloced= 100;
524 #define ADD_TO_T(c) \
525 *t++=c;\
526 if (t-target == talloced) {\
527 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
528 t = target+talloced;\
529 talloced*=2;\
532 if (from) {
533 f=from;
534 while (*f) {
535 if (*f=='%') {
536 int insertnr;
537 char *fmtstr,*sprintfbuf,*x,*lastf;
538 DWORD *argliststart;
540 fmtstr = NULL;
541 lastf = f;
542 f++;
543 if (!*f) {
544 ADD_TO_T('%');
545 continue;
547 switch (*f) {
548 case '1':case '2':case '3':case '4':case '5':
549 case '6':case '7':case '8':case '9':
550 insertnr=*f-'0';
551 switch (f[1]) {
552 case '0':case '1':case '2':case '3':
553 case '4':case '5':case '6':case '7':
554 case '8':case '9':
555 f++;
556 insertnr=insertnr*10+*f-'0';
557 f++;
558 break;
559 default:
560 f++;
561 break;
563 if (*f=='!') {
564 f++;
565 if (NULL!=(x=strchr(f,'!'))) {
566 *x='\0';
567 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f)+2);
568 sprintf(fmtstr,"%%%s",f);
569 f=x+1;
570 } else {
571 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f));
572 sprintf(fmtstr,"%%%s",f);
573 f+=strlen(f); /*at \0*/
575 } else
576 fmtstr=HEAP_strdupA(GetProcessHeap(),0,"%s");
577 if (args) {
578 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
579 argliststart=args+insertnr-1;
580 else
581 /* FIXME: not sure that this is
582 * correct for unix-c-varargs.
584 argliststart=((DWORD*)&args)+insertnr-1;
586 if (fmtstr[strlen(fmtstr)]=='s')
587 sprintfbuf=HeapAlloc(GetProcessHeap(),0,strlen((LPSTR)argliststart[0])+1);
588 else
589 sprintfbuf=HeapAlloc(GetProcessHeap(),0,100);
591 /* CMF - This makes a BIG assumption about va_list */
592 vsprintf(sprintfbuf, fmtstr, (va_list) argliststart);
593 x=sprintfbuf;
594 while (*x) {
595 ADD_TO_T(*x++);
597 HeapFree(GetProcessHeap(),0,sprintfbuf);
598 } else {
599 /* NULL args - copy formatstr
600 * (probably wrong)
602 while (lastf<f) {
603 ADD_TO_T(*lastf++);
606 HeapFree(GetProcessHeap(),0,fmtstr);
607 break;
608 case 'n':
609 /* FIXME: perhaps add \r too? */
610 ADD_TO_T('\n');
611 f++;
612 break;
613 case '0':
614 nolinefeed=1;
615 f++;
616 break;
617 default:ADD_TO_T(*f++)
618 break;
621 } else {
622 ADD_TO_T(*f++)
625 *t='\0';
627 if (!nolinefeed && t[-1]!='\n')
628 ADD_TO_T('\n');
629 talloced = strlen(target)+1;
630 if (nSize && talloced<nSize) {
631 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
633 if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
634 /* nSize is the MINIMUM size */
635 *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc32(GMEM_ZEROINIT,talloced);
636 memcpy(*(LPSTR*)lpBuffer,target,talloced);
637 } else
638 strncpy(lpBuffer,target,nSize);
639 HeapFree(GetProcessHeap(),0,target);
640 if (from) HeapFree(GetProcessHeap(),0,from);
641 return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
642 strlen(*(LPSTR*)lpBuffer):
643 strlen(lpBuffer);
645 #undef ADD_TO_T
647 /***********************************************************************
648 * FormatMessageA (KERNEL32.138) Emulator Version
650 DWORD
651 WIN32_FormatMessage32A(DWORD *args) {
652 DWORD dwFlags = args[0];
653 LPCVOID lpSource = (LPCVOID)args[1];
654 DWORD dwMessageId = args[2];
655 DWORD dwLanguageId = args[3];
656 LPSTR lpBuffer = (LPSTR)args[4];
657 DWORD nSize = args[5];
658 DWORD *xargs;
660 /* convert possible varargs to an argument array look-a-like */
662 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY) {
663 xargs=(DWORD*)args[6];
664 } else {
665 /* args[6] is a pointer to a pointer to the start of
666 * a list of arguments.
668 if (args[6])
669 xargs=(DWORD*)(((DWORD*)args[6])[0]);
670 else
671 xargs=NULL;
672 dwFlags|=FORMAT_MESSAGE_ARGUMENT_ARRAY;
674 return FormatMessage32A(
675 dwFlags,
676 lpSource,
677 dwMessageId,
678 dwLanguageId,
679 lpBuffer,
680 nSize,
681 xargs
685 DWORD
686 FormatMessage32W(
687 DWORD dwFlags,
688 LPCVOID lpSource,
689 DWORD dwMessageId,
690 DWORD dwLanguageId,
691 LPWSTR lpBuffer,
692 DWORD nSize,
693 LPDWORD args /* va_list *args */
695 LPSTR target,t;
696 DWORD talloced;
697 LPSTR from,f;
698 DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
699 DWORD nolinefeed = 0;
701 dprintf_resource(stddeb,
702 "FormatMessage32A(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
703 dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args
705 if (width)
706 fprintf(stdnimp," - line wrapping not supported.\n");
707 from = NULL;
708 if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
709 from = HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)lpSource);
710 if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) {
711 /* gather information from system message tables ... */
712 from = HeapAlloc( GetProcessHeap(),0,200 );
713 sprintf(from,"Systemmessage, messageid = 0x%08lx\n",dwMessageId);
715 if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) {
716 INT32 bufsize;
718 dwMessageId &= 0xFFFF;
719 bufsize=LoadMessage32A(0,dwMessageId,dwLanguageId,NULL,100);
720 if (bufsize)
722 from = HeapAlloc( GetProcessHeap(), 0, bufsize + 1 );
723 LoadMessage32A(0,dwMessageId,dwLanguageId,from,bufsize+1);
726 target = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100 );
727 t = target;
728 talloced= 100;
730 #define ADD_TO_T(c) \
731 *t++=c;\
732 if (t-target == talloced) {\
733 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
734 t = target+talloced;\
735 talloced*=2;\
738 if (from) {
739 f=from;
740 while (*f) {
741 if (*f=='%') {
742 int insertnr;
743 char *fmtstr,*sprintfbuf,*x;
744 DWORD *argliststart;
746 fmtstr = NULL;
747 f++;
748 if (!*f) {
749 ADD_TO_T('%');
750 continue;
752 switch (*f) {
753 case '1':case '2':case '3':case '4':case '5':
754 case '6':case '7':case '8':case '9':
755 insertnr=*f-'0';
756 switch (f[1]) {
757 case '0':case '1':case '2':case '3':
758 case '4':case '5':case '6':case '7':
759 case '8':case '9':
760 f++;
761 insertnr=insertnr*10+*f-'0';
762 f++;
763 break;
764 default:
765 f++;
766 break;
768 if (*f=='!') {
769 f++;
770 if (NULL!=(x=strchr(f,'!')))
772 *x='\0';
773 fmtstr=HeapAlloc( GetProcessHeap(), 0, strlen(f)+2);
774 sprintf(fmtstr,"%%%s",f);
775 f=x+1;
776 } else {
777 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f));
778 sprintf(fmtstr,"%%%s",f);
779 f+=strlen(f); /*at \0*/
781 } else
782 fmtstr=HEAP_strdupA( GetProcessHeap(),0,"%s");
783 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
784 argliststart=args+insertnr-1;
785 else
786 /* FIXME: not sure that this is
787 * correct for unix-c-varargs.
789 argliststart=((DWORD*)&args)+insertnr-1;
791 if (fmtstr[strlen(fmtstr)]=='s') {
792 DWORD xarr[3];
794 xarr[0]=(DWORD)HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)(*(argliststart+0)));
795 /* possible invalid pointers */
796 xarr[1]=*(argliststart+1);
797 xarr[2]=*(argliststart+2);
798 sprintfbuf=HeapAlloc(GetProcessHeap(),0,lstrlen32W((LPWSTR)argliststart[0])*2+1);
800 /* CMF - This makes a BIG assumption about va_list */
801 vsprintf(sprintfbuf, fmtstr, (va_list) xarr);
802 } else {
803 sprintfbuf=HeapAlloc(GetProcessHeap(),0,100);
805 /* CMF - This makes a BIG assumption about va_list */
806 vsprintf(sprintfbuf, fmtstr, (va_list) argliststart);
808 x=sprintfbuf;
809 while (*x) {
810 ADD_TO_T(*x++);
812 HeapFree(GetProcessHeap(),0,sprintfbuf);
813 HeapFree(GetProcessHeap(),0,fmtstr);
814 break;
815 case 'n':
816 /* FIXME: perhaps add \r too? */
817 ADD_TO_T('\n');
818 f++;
819 break;
820 case '0':
821 nolinefeed=1;
822 f++;
823 break;
824 default:ADD_TO_T(*f++)
825 break;
828 } else {
829 ADD_TO_T(*f++)
832 *t='\0';
834 if (!nolinefeed && t[-1]!='\n')
835 ADD_TO_T('\n');
836 talloced = strlen(target)+1;
837 if (nSize && talloced<nSize)
838 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
839 if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
840 /* nSize is the MINIMUM size */
841 *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc32(GMEM_ZEROINIT,talloced*2+2);
842 lstrcpynAtoW(*(LPWSTR*)lpBuffer,target,talloced);
843 } else
844 lstrcpynAtoW(lpBuffer,target,nSize);
845 HeapFree(GetProcessHeap(),0,target);
846 if (from) HeapFree(GetProcessHeap(),0,from);
847 return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
848 lstrlen32W(*(LPWSTR*)lpBuffer):
849 lstrlen32W(lpBuffer);
851 #undef ADD_TO_T
853 /***********************************************************************
854 * FormatMessageA (KERNEL32.138) Emulator Version
856 DWORD
857 WIN32_FormatMessage32W(DWORD *args) {
858 DWORD dwFlags = args[0];
859 LPCVOID lpSource = (LPCVOID)args[1];
860 DWORD dwMessageId = args[2];
861 DWORD dwLanguageId = args[3];
862 LPWSTR lpBuffer = (LPWSTR)args[4];
863 DWORD nSize = args[5];
864 DWORD *xargs;
866 /* convert possible varargs to an argument array look-a-like */
868 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY) {
869 xargs=(DWORD*)args[6];
870 } else {
871 /* args[6] is a pointer to a pointer to the start of
872 * a list of arguments.
874 if (args[6])
875 xargs=(DWORD*)(((DWORD*)args[6])[0]);
876 else
877 xargs=NULL;
878 dwFlags|=FORMAT_MESSAGE_ARGUMENT_ARRAY;
880 return FormatMessage32W(
881 dwFlags,
882 lpSource,
883 dwMessageId,
884 dwLanguageId,
885 lpBuffer,
886 nSize,
887 xargs