Release 970509
[wine/multimedia.git] / misc / lstr.c
blob7f565caf8f9b546ab1a99105741402cb16bf38dd
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;
538 DWORD *argliststart;
540 fmtstr = NULL;
541 f++;
542 if (!*f) {
543 ADD_TO_T('%');
544 continue;
546 switch (*f) {
547 case '1':case '2':case '3':case '4':case '5':
548 case '6':case '7':case '8':case '9':
549 insertnr=*f-'0';
550 switch (f[1]) {
551 case '0':case '1':case '2':case '3':
552 case '4':case '5':case '6':case '7':
553 case '8':case '9':
554 f++;
555 insertnr=insertnr*10+*f-'0';
556 f++;
557 break;
558 default:
559 f++;
560 break;
562 if (*f=='!') {
563 f++;
564 if (NULL!=(x=strchr(f,'!'))) {
565 *x='\0';
566 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f)+2);
567 sprintf(fmtstr,"%%%s",f);
568 f=x+1;
569 } else {
570 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f));
571 sprintf(fmtstr,"%%%s",f);
572 f+=strlen(f); /*at \0*/
574 } else
575 fmtstr=HEAP_strdupA(GetProcessHeap(),0,"%s");
576 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
577 argliststart=args+insertnr-1;
578 else
579 /* FIXME: not sure that this is
580 * correct for unix-c-varargs.
582 argliststart=((DWORD*)&args)+insertnr-1;
584 if (fmtstr[strlen(fmtstr)]=='s')
585 sprintfbuf=HeapAlloc(GetProcessHeap(),0,strlen((LPSTR)argliststart[0])+1);
586 else
587 sprintfbuf=HeapAlloc(GetProcessHeap(),0,100);
589 /* CMF - This makes a BIG assumption about va_list */
590 vsprintf(sprintfbuf, fmtstr, (va_list) argliststart);
591 x=sprintfbuf;
592 while (*x) {
593 ADD_TO_T(*x++);
595 HeapFree(GetProcessHeap(),0,sprintfbuf);
596 HeapFree(GetProcessHeap(),0,fmtstr);
597 break;
598 case 'n':
599 /* FIXME: perhaps add \r too? */
600 ADD_TO_T('\n');
601 f++;
602 break;
603 case '0':
604 nolinefeed=1;
605 f++;
606 break;
607 default:ADD_TO_T(*f++)
608 break;
611 } else {
612 ADD_TO_T(*f++)
615 *t='\0';
617 if (!nolinefeed && t[-1]!='\n')
618 ADD_TO_T('\n');
619 talloced = strlen(target)+1;
620 if (nSize && talloced<nSize) {
621 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
623 if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
624 /* nSize is the MINIMUM size */
625 *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc32(GMEM_ZEROINIT,talloced);
626 memcpy(*(LPSTR*)lpBuffer,target,talloced);
627 } else
628 strncpy(lpBuffer,target,nSize);
629 HeapFree(GetProcessHeap(),0,target);
630 if (from) HeapFree(GetProcessHeap(),0,from);
631 return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
632 strlen(*(LPSTR*)lpBuffer):
633 strlen(lpBuffer);
635 #undef ADD_TO_T
637 /***********************************************************************
638 * FormatMessageA (KERNEL32.138) Emulator Version
640 DWORD
641 WIN32_FormatMessage32A(DWORD *args) {
642 DWORD dwFlags = args[0];
643 LPCVOID lpSource = (LPCVOID)args[1];
644 DWORD dwMessageId = args[2];
645 DWORD dwLanguageId = args[3];
646 LPSTR lpBuffer = (LPSTR)args[4];
647 DWORD nSize = args[5];
648 DWORD *xargs;
650 /* convert possible varargs to an argument array look-a-like */
652 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY) {
653 xargs=(DWORD*)args[6];
654 } else {
655 /* args[6] is a pointer to a pointer to the start of
656 * a list of arguments.
658 if (args[6])
659 xargs=(DWORD*)(((DWORD*)args[6])[0]);
660 else
661 xargs=NULL;
662 dwFlags|=FORMAT_MESSAGE_ARGUMENT_ARRAY;
664 return FormatMessage32A(
665 dwFlags,
666 lpSource,
667 dwMessageId,
668 dwLanguageId,
669 lpBuffer,
670 nSize,
671 xargs
675 DWORD
676 FormatMessage32W(
677 DWORD dwFlags,
678 LPCVOID lpSource,
679 DWORD dwMessageId,
680 DWORD dwLanguageId,
681 LPWSTR lpBuffer,
682 DWORD nSize,
683 LPDWORD args /* va_list *args */
685 LPSTR target,t;
686 DWORD talloced;
687 LPSTR from,f;
688 DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
689 DWORD nolinefeed = 0;
691 dprintf_resource(stddeb,
692 "FormatMessage32A(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
693 dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args
695 if (width)
696 fprintf(stdnimp," - line wrapping not supported.\n");
697 from = NULL;
698 if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
699 from = HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)lpSource);
700 if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) {
701 /* gather information from system message tables ... */
702 from = HeapAlloc( GetProcessHeap(),0,200 );
703 sprintf(from,"Systemmessage, messageid = 0x%08lx\n",dwMessageId);
705 if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) {
706 INT32 bufsize;
708 dwMessageId &= 0xFFFF;
709 bufsize=LoadMessage32A(0,dwMessageId,dwLanguageId,NULL,100);
710 if (bufsize)
712 from = HeapAlloc( GetProcessHeap(), 0, bufsize + 1 );
713 LoadMessage32A(0,dwMessageId,dwLanguageId,from,bufsize+1);
716 target = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100 );
717 t = target;
718 talloced= 100;
720 #define ADD_TO_T(c) \
721 *t++=c;\
722 if (t-target == talloced) {\
723 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
724 t = target+talloced;\
725 talloced*=2;\
728 if (from) {
729 f=from;
730 while (*f) {
731 if (*f=='%') {
732 int insertnr;
733 char *fmtstr,*sprintfbuf,*x;
734 DWORD *argliststart;
736 fmtstr = NULL;
737 f++;
738 if (!*f) {
739 ADD_TO_T('%');
740 continue;
742 switch (*f) {
743 case '1':case '2':case '3':case '4':case '5':
744 case '6':case '7':case '8':case '9':
745 insertnr=*f-'0';
746 switch (f[1]) {
747 case '0':case '1':case '2':case '3':
748 case '4':case '5':case '6':case '7':
749 case '8':case '9':
750 f++;
751 insertnr=insertnr*10+*f-'0';
752 f++;
753 break;
754 default:
755 f++;
756 break;
758 if (*f=='!') {
759 f++;
760 if (NULL!=(x=strchr(f,'!')))
762 *x='\0';
763 fmtstr=HeapAlloc( GetProcessHeap(), 0, strlen(f)+2);
764 sprintf(fmtstr,"%%%s",f);
765 f=x+1;
766 } else {
767 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f));
768 sprintf(fmtstr,"%%%s",f);
769 f+=strlen(f); /*at \0*/
771 } else
772 fmtstr=HEAP_strdupA( GetProcessHeap(),0,"%s");
773 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
774 argliststart=args+insertnr-1;
775 else
776 /* FIXME: not sure that this is
777 * correct for unix-c-varargs.
779 argliststart=((DWORD*)&args)+insertnr-1;
781 if (fmtstr[strlen(fmtstr)]=='s') {
782 DWORD xarr[3];
784 xarr[0]=(DWORD)HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)(*(argliststart+0)));
785 /* possible invalid pointers */
786 xarr[1]=*(argliststart+1);
787 xarr[2]=*(argliststart+2);
788 sprintfbuf=HeapAlloc(GetProcessHeap(),0,lstrlen32W((LPWSTR)argliststart[0])*2+1);
790 /* CMF - This makes a BIG assumption about va_list */
791 vsprintf(sprintfbuf, fmtstr, (va_list) xarr);
792 } else {
793 sprintfbuf=HeapAlloc(GetProcessHeap(),0,100);
795 /* CMF - This makes a BIG assumption about va_list */
796 vsprintf(sprintfbuf, fmtstr, (va_list) argliststart);
798 x=sprintfbuf;
799 while (*x) {
800 ADD_TO_T(*x++);
802 HeapFree(GetProcessHeap(),0,sprintfbuf);
803 HeapFree(GetProcessHeap(),0,fmtstr);
804 break;
805 case 'n':
806 /* FIXME: perhaps add \r too? */
807 ADD_TO_T('\n');
808 f++;
809 break;
810 case '0':
811 nolinefeed=1;
812 f++;
813 break;
814 default:ADD_TO_T(*f++)
815 break;
818 } else {
819 ADD_TO_T(*f++)
822 *t='\0';
824 if (!nolinefeed && t[-1]!='\n')
825 ADD_TO_T('\n');
826 talloced = strlen(target)+1;
827 if (nSize && talloced<nSize)
828 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
829 if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
830 /* nSize is the MINIMUM size */
831 *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc32(GMEM_ZEROINIT,talloced*2+2);
832 lstrcpynAtoW(*(LPWSTR*)lpBuffer,target,talloced);
833 } else
834 lstrcpynAtoW(lpBuffer,target,nSize);
835 HeapFree(GetProcessHeap(),0,target);
836 if (from) HeapFree(GetProcessHeap(),0,from);
837 return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
838 lstrlen32W(*(LPWSTR*)lpBuffer):
839 lstrlen32W(lpBuffer);
841 #undef ADD_TO_T
843 /***********************************************************************
844 * FormatMessageA (KERNEL32.138) Emulator Version
846 DWORD
847 WIN32_FormatMessage32W(DWORD *args) {
848 DWORD dwFlags = args[0];
849 LPCVOID lpSource = (LPCVOID)args[1];
850 DWORD dwMessageId = args[2];
851 DWORD dwLanguageId = args[3];
852 LPWSTR lpBuffer = (LPWSTR)args[4];
853 DWORD nSize = args[5];
854 DWORD *xargs;
856 /* convert possible varargs to an argument array look-a-like */
858 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY) {
859 xargs=(DWORD*)args[6];
860 } else {
861 /* args[6] is a pointer to a pointer to the start of
862 * a list of arguments.
864 if (args[6])
865 xargs=(DWORD*)(((DWORD*)args[6])[0]);
866 else
867 xargs=NULL;
868 dwFlags|=FORMAT_MESSAGE_ARGUMENT_ARRAY;
870 return FormatMessage32W(
871 dwFlags,
872 lpSource,
873 dwMessageId,
874 dwLanguageId,
875 lpBuffer,
876 nSize,
877 xargs