Release 970305
[wine/multimedia.git] / misc / lstr.c
blob29c60ee8f26893f645320339886680d30d33129c
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 /* gather information from system message tables ... */
508 fprintf(stdnimp," - FORMAT_MESSAGE_FROM_SYSTEM not implemented.\n");
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);
588 vsprintf(sprintfbuf,fmtstr,argliststart);
589 x=sprintfbuf;
590 while (*x) {
591 ADD_TO_T(*x++);
593 HeapFree(GetProcessHeap(),0,sprintfbuf);
594 HeapFree(GetProcessHeap(),0,fmtstr);
595 break;
596 case 'n':
597 /* FIXME: perhaps add \r too? */
598 ADD_TO_T('\n');
599 f++;
600 break;
601 case '0':
602 nolinefeed=1;
603 f++;
604 break;
605 default:ADD_TO_T(*f++)
606 break;
609 } else {
610 ADD_TO_T(*f++)
613 *t='\0';
615 if (!nolinefeed && t[-1]!='\n')
616 ADD_TO_T('\n');
617 talloced = strlen(target)+1;
618 if (nSize && talloced<nSize) {
619 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
621 if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
622 /* nSize is the MINIMUM size */
623 *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc32(GMEM_ZEROINIT,talloced);
624 memcpy(*(LPSTR*)lpBuffer,target,talloced);
625 } else
626 strncpy(lpBuffer,target,nSize);
627 HeapFree(GetProcessHeap(),0,target);
628 if (from) HeapFree(GetProcessHeap(),0,from);
629 return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
630 strlen(*(LPSTR*)lpBuffer):
631 strlen(lpBuffer);
633 #undef ADD_TO_T
635 /***********************************************************************
636 * FormatMessageA (KERNEL32.138) Emulator Version
638 DWORD
639 WIN32_FormatMessage32A(DWORD *args) {
640 DWORD dwFlags = args[0];
641 LPCVOID lpSource = (LPCVOID)args[1];
642 DWORD dwMessageId = args[2];
643 DWORD dwLanguageId = args[3];
644 LPSTR lpBuffer = (LPSTR)args[4];
645 DWORD nSize = args[5];
646 DWORD *xargs;
648 /* convert possible varargs to an argument array look-a-like */
650 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY) {
651 xargs=(DWORD*)args[6];
652 } else {
653 /* args[6] is a pointer to a pointer to the start of
654 * a list of arguments.
656 if (args[6])
657 xargs=(DWORD*)(((DWORD*)args[6])[0]);
658 else
659 xargs=NULL;
660 dwFlags|=FORMAT_MESSAGE_ARGUMENT_ARRAY;
662 return FormatMessage32A(
663 dwFlags,
664 lpSource,
665 dwMessageId,
666 dwLanguageId,
667 lpBuffer,
668 nSize,
669 xargs
673 DWORD
674 FormatMessage32W(
675 DWORD dwFlags,
676 LPCVOID lpSource,
677 DWORD dwMessageId,
678 DWORD dwLanguageId,
679 LPWSTR lpBuffer,
680 DWORD nSize,
681 LPDWORD args /* va_list *args */
683 LPSTR target,t;
684 DWORD talloced;
685 LPSTR from,f;
686 DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
687 DWORD nolinefeed = 0;
689 dprintf_resource(stddeb,
690 "FormatMessage32A(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
691 dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args
693 if (width)
694 fprintf(stdnimp," - line wrapping not supported.\n");
695 from = NULL;
696 if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
697 from = HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)lpSource);
698 if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) {
699 /* gather information from system message tables ... */
700 fprintf(stdnimp," - FORMAT_MESSAGE_FROM_SYSTEM not implemented.\n");
702 if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) {
703 INT32 bufsize;
705 dwMessageId &= 0xFFFF;
706 bufsize=LoadMessage32A(0,dwMessageId,dwLanguageId,NULL,100);
707 if (bufsize)
709 from = HeapAlloc( GetProcessHeap(), 0, bufsize + 1 );
710 LoadMessage32A(0,dwMessageId,dwLanguageId,from,bufsize+1);
713 target = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100 );
714 t = target;
715 talloced= 100;
717 #define ADD_TO_T(c) \
718 *t++=c;\
719 if (t-target == talloced) {\
720 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
721 t = target+talloced;\
722 talloced*=2;\
725 if (from) {
726 f=from;
727 while (*f) {
728 if (*f=='%') {
729 int insertnr;
730 char *fmtstr,*sprintfbuf,*x;
731 DWORD *argliststart;
733 fmtstr = NULL;
734 f++;
735 if (!*f) {
736 ADD_TO_T('%');
737 continue;
739 switch (*f) {
740 case '1':case '2':case '3':case '4':case '5':
741 case '6':case '7':case '8':case '9':
742 insertnr=*f-'0';
743 switch (f[1]) {
744 case '0':case '1':case '2':case '3':
745 case '4':case '5':case '6':case '7':
746 case '8':case '9':
747 f++;
748 insertnr=insertnr*10+*f-'0';
749 f++;
750 break;
751 default:
752 f++;
753 break;
755 if (*f=='!') {
756 f++;
757 if (NULL!=(x=strchr(f,'!')))
759 *x='\0';
760 fmtstr=HeapAlloc( GetProcessHeap(), 0, strlen(f)+2);
761 sprintf(fmtstr,"%%%s",f);
762 f=x+1;
763 } else {
764 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f));
765 sprintf(fmtstr,"%%%s",f);
766 f+=strlen(f); /*at \0*/
768 } else
769 fmtstr=HEAP_strdupA( GetProcessHeap(),0,"%s");
770 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
771 argliststart=args+insertnr-1;
772 else
773 /* FIXME: not sure that this is
774 * correct for unix-c-varargs.
776 argliststart=((DWORD*)&args)+insertnr-1;
778 if (fmtstr[strlen(fmtstr)]=='s') {
779 DWORD xarr[3];
781 xarr[0]=(DWORD)HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)(*(argliststart+0)));
782 /* possible invalid pointers */
783 xarr[1]=*(argliststart+1);
784 xarr[2]=*(argliststart+2);
785 sprintfbuf=HeapAlloc(GetProcessHeap(),0,lstrlen32W((LPWSTR)argliststart[0])*2+1);
786 vsprintf(sprintfbuf,fmtstr,xarr);
787 } else {
788 sprintfbuf=HeapAlloc(GetProcessHeap(),0,100);
789 vsprintf(sprintfbuf,fmtstr,argliststart);
791 x=sprintfbuf;
792 while (*x) {
793 ADD_TO_T(*x++);
795 HeapFree(GetProcessHeap(),0,sprintfbuf);
796 HeapFree(GetProcessHeap(),0,fmtstr);
797 break;
798 case 'n':
799 /* FIXME: perhaps add \r too? */
800 ADD_TO_T('\n');
801 f++;
802 break;
803 case '0':
804 nolinefeed=1;
805 f++;
806 break;
807 default:ADD_TO_T(*f++)
808 break;
811 } else {
812 ADD_TO_T(*f++)
815 *t='\0';
817 if (!nolinefeed && t[-1]!='\n')
818 ADD_TO_T('\n');
819 talloced = strlen(target)+1;
820 if (nSize && talloced<nSize)
821 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
822 if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
823 /* nSize is the MINIMUM size */
824 *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc32(GMEM_ZEROINIT,talloced*2+2);
825 lstrcpynAtoW(*(LPWSTR*)lpBuffer,target,talloced);
826 } else
827 lstrcpynAtoW(lpBuffer,target,nSize);
828 HeapFree(GetProcessHeap(),0,target);
829 if (from) HeapFree(GetProcessHeap(),0,from);
830 return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
831 lstrlen32W(*(LPWSTR*)lpBuffer):
832 lstrlen32W(lpBuffer);
834 #undef ADD_TO_T
836 /***********************************************************************
837 * FormatMessageA (KERNEL32.138) Emulator Version
839 DWORD
840 WIN32_FormatMessage32W(DWORD *args) {
841 DWORD dwFlags = args[0];
842 LPCVOID lpSource = (LPCVOID)args[1];
843 DWORD dwMessageId = args[2];
844 DWORD dwLanguageId = args[3];
845 LPWSTR lpBuffer = (LPWSTR)args[4];
846 DWORD nSize = args[5];
847 DWORD *xargs;
849 /* convert possible varargs to an argument array look-a-like */
851 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY) {
852 xargs=(DWORD*)args[6];
853 } else {
854 /* args[6] is a pointer to a pointer to the start of
855 * a list of arguments.
857 if (args[6])
858 xargs=(DWORD*)(((DWORD*)args[6])[0]);
859 else
860 xargs=NULL;
861 dwFlags|=FORMAT_MESSAGE_ARGUMENT_ARRAY;
863 return FormatMessage32W(
864 dwFlags,
865 lpSource,
866 dwMessageId,
867 dwLanguageId,
868 lpBuffer,
869 nSize,
870 xargs