Optimized include/*.h: (recursively) include all headers needed by
[wine/testsucceed.git] / misc / lstr.c
blob482020506f099cd45ce8abbcc9c806a1d1fe1a27
1 /*
2 * String functions
4 * Copyright 1993 Yngvi Sigurjonsson (yngvi@hafro.is)
5 * Copyright 1996 Marcus Meissner
6 */
8 #include "config.h"
10 #include <stdarg.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <ctype.h>
15 #ifdef HAVE_WCTYPE_H
16 # include <wctype.h>
17 #else
18 # define iswalnum(c) isalnum(c)
19 # define iswalpha(c) isalpha(c)
20 # define iswupper(c) isupper(c)
21 # define iswlower(c) islower(c)
22 #endif /* HAVE_WCTYPE_H */
25 #include "windows.h"
26 #include "winnt.h" /* HEAP_ macros */
27 #include "task.h"
28 #include "heap.h"
29 #include "ldt.h"
30 #include "stackframe.h"
31 #include "module.h"
32 #include "debug.h"
34 extern const WORD OLE2NLS_CT_CType3_LUT[]; /* FIXME: does not belong here */
37 /* Funny to divide them between user and kernel. */
39 /* be careful: always use functions from wctype.h if character > 255 */
42 * Unicode case conversion routines ... these should be used where
43 * toupper/tolower are used for ASCII.
45 #ifndef HAVE_WCTYPE_H
46 /* FIXME: should probably get rid of wctype.h altogether */
47 #include "casemap.h"
49 WCHAR towupper(WCHAR code)
51 const WCHAR * ptr = uprtable[HIBYTE(code)];
52 return ptr ? ptr[LOBYTE(code)] : code;
55 WCHAR towlower(WCHAR code)
57 const WCHAR * ptr = lwrtable[HIBYTE(code)];
58 return ptr ? ptr[LOBYTE(code)] : code;
60 #endif /* HAVE_WCTYPE_H */
62 /***********************************************************************
63 * IsCharAlpha (USER.433)
65 BOOL16 WINAPI IsCharAlpha16(CHAR ch)
67 return isalpha(ch); /* This is probably not right for NLS */
70 /***********************************************************************
71 * IsCharAlphanumeric (USER.434)
73 BOOL16 WINAPI IsCharAlphaNumeric16(CHAR ch)
75 return isalnum(ch);
78 /***********************************************************************
79 * IsCharUpper (USER.435)
81 BOOL16 WINAPI IsCharUpper16(CHAR ch)
83 return isupper(ch);
86 /***********************************************************************
87 * IsCharLower (USER.436)
89 BOOL16 WINAPI IsCharLower16(CHAR ch)
91 return islower(ch);
94 /***********************************************************************
95 * AnsiUpper16 (USER.431)
97 SEGPTR WINAPI AnsiUpper16( SEGPTR strOrChar )
99 /* I am not sure if the locale stuff works with toupper, but then again
100 I am not sure if the Linux libc locale stuffs works at all */
102 /* uppercase only one char if strOrChar < 0x10000 */
103 if (HIWORD(strOrChar))
105 char *s;
106 for (s = PTR_SEG_TO_LIN(strOrChar); *s; s++) *s = toupper(*s);
107 return strOrChar;
109 else return toupper((char)strOrChar);
113 /***********************************************************************
114 * AnsiUpperBuff16 (USER.437)
116 UINT16 WINAPI AnsiUpperBuff16( LPSTR str, UINT16 len )
118 UINT32 count = len ? len : 65536;
119 for (; count; count--, str++) *str = toupper(*str);
120 return len;
123 /***********************************************************************
124 * AnsiLower16 (USER.432)
126 SEGPTR WINAPI AnsiLower16( SEGPTR strOrChar )
128 /* I am not sure if the locale stuff works with toupper, but then again
129 I am not sure if the Linux libc locale stuffs works at all */
131 /* lowercase only one char if strOrChar < 0x10000 */
132 if (HIWORD(strOrChar))
134 char *s;
135 for (s = PTR_SEG_TO_LIN( strOrChar ); *s; s++) *s = tolower( *s );
136 return strOrChar;
138 else return tolower((char)strOrChar);
142 /***********************************************************************
143 * AnsiLowerBuff16 (USER.438)
145 UINT16 WINAPI AnsiLowerBuff16( LPSTR str, UINT16 len )
147 UINT32 count = len ? len : 65536;
148 for (; count; count--, str++) *str = tolower(*str);
149 return len;
153 /***********************************************************************
154 * AnsiNext16 (USER.472)
156 SEGPTR WINAPI AnsiNext16(SEGPTR current)
158 return (*(char *)PTR_SEG_TO_LIN(current)) ? current + 1 : current;
162 /***********************************************************************
163 * AnsiPrev16 (USER.473)
165 SEGPTR WINAPI AnsiPrev16( SEGPTR start, SEGPTR current )
167 return (current == start) ? start : current - 1;
171 /***********************************************************************
172 * OutputDebugString16 (KERNEL.115)
174 void WINAPI OutputDebugString16( LPCSTR str )
176 char module[10];
177 if (!GetModuleName( GetCurrentTask(), module, sizeof(module) ))
178 strcpy( module, "???" );
180 DUMP( "%s says %s\n", module, debugstr_a(str) );
184 /***********************************************************************
185 * OutputDebugString32A (KERNEL32
187 void WINAPI OutputDebugString32A( LPCSTR str )
189 OutputDebugString16( str );
194 /***********************************************************************
195 * OutputDebugString32W (KERNEL32
197 void WINAPI OutputDebugString32W( LPCWSTR str )
199 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
200 OutputDebugString32A( p );
201 HeapFree( GetProcessHeap(), 0, p );
206 /***********************************************************************
207 * CharNext32A (USER32.29)
209 LPSTR WINAPI CharNext32A( LPCSTR ptr )
211 if (!*ptr) return (LPSTR)ptr;
212 if (IsDBCSLeadByte32( *ptr )) return (LPSTR)(ptr + 2);
213 return (LPSTR)(ptr + 1);
217 /***********************************************************************
218 * CharNextEx32A (USER32.30)
220 LPSTR WINAPI CharNextEx32A( WORD codepage, LPCSTR ptr, DWORD flags )
222 if (!*ptr) return (LPSTR)ptr;
223 if (IsDBCSLeadByteEx( codepage, *ptr )) return (LPSTR)(ptr + 2);
224 return (LPSTR)(ptr + 1);
228 /***********************************************************************
229 * CharNextExW (USER32.31)
231 LPWSTR WINAPI CharNextEx32W(WORD codepage,LPCWSTR x,DWORD flags)
233 /* FIXME: add DBCS / codepage stuff */
234 if (*x) return (LPWSTR)(x+1);
235 else return (LPWSTR)x;
238 /***********************************************************************
239 * CharNextW (USER32.32)
241 LPWSTR WINAPI CharNext32W(LPCWSTR x)
243 if (*x) return (LPWSTR)(x+1);
244 else return (LPWSTR)x;
247 /***********************************************************************
248 * CharPrev32A (USER32.33)
250 LPSTR WINAPI CharPrev32A( LPCSTR start, LPCSTR ptr )
252 while (*start && (start < ptr))
254 LPCSTR next = CharNext32A( start );
255 if (next >= ptr) break;
256 start = next;
258 return (LPSTR)start;
262 /***********************************************************************
263 * CharPrevEx32A (USER32.34)
265 LPSTR WINAPI CharPrevEx32A( WORD codepage, LPCSTR start, LPCSTR ptr, DWORD flags )
267 while (*start && (start < ptr))
269 LPCSTR next = CharNextEx32A( codepage, start, flags );
270 if (next > ptr) break;
271 start = next;
273 return (LPSTR)start;
277 /***********************************************************************
278 * CharPrevExW (USER32.35)
280 LPWSTR WINAPI CharPrevEx32W(WORD codepage,LPCWSTR start,LPCWSTR x,DWORD flags)
282 /* FIXME: add DBCS / codepage stuff */
283 if (x>start) return (LPWSTR)(x-1);
284 else return (LPWSTR)x;
287 /***********************************************************************
288 * CharPrevW (USER32.36)
290 LPWSTR WINAPI CharPrev32W(LPCWSTR start,LPCWSTR x)
292 if (x>start) return (LPWSTR)(x-1);
293 else return (LPWSTR)x;
296 /***********************************************************************
297 * CharLowerA (USER32.25)
298 * FIXME: handle current locale
300 LPSTR WINAPI CharLower32A(LPSTR x)
302 LPSTR s;
304 if (HIWORD(x))
306 s=x;
307 while (*s)
309 *s=tolower(*s);
310 s++;
312 return x;
314 else return (LPSTR)tolower((char)(int)x);
317 /***********************************************************************
318 * CharLowerBuffA (USER32.26)
319 * FIXME: handle current locale
321 DWORD WINAPI CharLowerBuff32A(LPSTR x,DWORD buflen)
323 DWORD done=0;
325 if (!x) return 0; /* YES */
326 while (*x && (buflen--))
328 *x=tolower(*x);
329 x++;
330 done++;
332 return done;
335 /***********************************************************************
336 * CharLowerBuffW (USER32.27)
337 * FIXME: handle current locale
339 DWORD WINAPI CharLowerBuff32W(LPWSTR x,DWORD buflen)
341 DWORD done=0;
343 if (!x) return 0; /* YES */
344 while (*x && (buflen--))
346 *x=towlower(*x);
347 x++;
348 done++;
350 return done;
353 /***********************************************************************
354 * CharLowerW (USER32.28)
355 * FIXME: handle current locale
357 LPWSTR WINAPI CharLower32W(LPWSTR x)
359 if (HIWORD(x))
361 LPWSTR s = x;
362 while (*s)
364 *s=towlower(*s);
365 s++;
367 return x;
369 else return (LPWSTR)((UINT32)towlower(LOWORD(x)));
372 /***********************************************************************
373 * CharUpper32A (USER32.41)
374 * FIXME: handle current locale
376 LPSTR WINAPI CharUpper32A(LPSTR x)
378 if (HIWORD(x))
380 LPSTR s = x;
381 while (*s)
383 *s=toupper(*s);
384 s++;
386 return x;
388 return (LPSTR)toupper((char)(int)x);
391 /***********************************************************************
392 * CharUpperBuffA (USER32.42)
393 * FIXME: handle current locale
395 DWORD WINAPI CharUpperBuff32A(LPSTR x,DWORD buflen)
397 DWORD done=0;
399 if (!x) return 0; /* YES */
400 while (*x && (buflen--))
402 *x=toupper(*x);
403 x++;
404 done++;
406 return done;
409 /***********************************************************************
410 * CharUpperBuffW (USER32.43)
411 * FIXME: handle current locale
413 DWORD WINAPI CharUpperBuff32W(LPWSTR x,DWORD buflen)
415 DWORD done=0;
417 if (!x) return 0; /* YES */
418 while (*x && (buflen--))
420 *x=towupper(*x);
421 x++;
422 done++;
424 return done;
427 /***********************************************************************
428 * CharUpperW (USER32.44)
429 * FIXME: handle current locale
431 LPWSTR WINAPI CharUpper32W(LPWSTR x)
433 if (HIWORD(x))
435 LPWSTR s = x;
436 while (*s)
438 *s=towupper(*s);
439 s++;
441 return x;
443 else return (LPWSTR)((UINT32)towupper(LOWORD(x)));
446 /***********************************************************************
447 * IsCharAlphaA (USER32.331)
448 * FIXME: handle current locale
450 BOOL32 WINAPI IsCharAlpha32A(CHAR x)
452 return (OLE2NLS_CT_CType3_LUT[(unsigned char)x] & C3_ALPHA);
455 /***********************************************************************
456 * IsCharAlphaNumericA (USER32.332)
457 * FIXME: handle current locale
459 BOOL32 WINAPI IsCharAlphaNumeric32A(CHAR x)
461 return IsCharAlpha32A(x) || isdigit(x) ;
464 /***********************************************************************
465 * IsCharAlphaNumericW (USER32.333)
466 * FIXME: handle current locale
468 BOOL32 WINAPI IsCharAlphaNumeric32W(WCHAR x)
470 return iswalnum(x);
473 /***********************************************************************
474 * IsCharAlphaW (USER32.334)
475 * FIXME: handle current locale
477 BOOL32 WINAPI IsCharAlpha32W(WCHAR x)
479 return iswalpha(x);
482 /***********************************************************************
483 * IsCharLower32A (USER32.335)
484 * FIXME: handle current locale
486 BOOL32 WINAPI IsCharLower32A(CHAR x)
488 return islower(x);
491 /***********************************************************************
492 * IsCharLower32W (USER32.336)
493 * FIXME: handle current locale
495 BOOL32 WINAPI IsCharLower32W(WCHAR x)
497 return iswlower(x);
500 /***********************************************************************
501 * IsCharUpper32A (USER32.337)
502 * FIXME: handle current locale
504 BOOL32 WINAPI IsCharUpper32A(CHAR x)
506 return isupper(x);
509 /***********************************************************************
510 * IsCharUpper32W (USER32.338)
511 * FIXME: handle current locale
513 BOOL32 WINAPI IsCharUpper32W(WCHAR x)
515 return iswupper(x);
518 /***********************************************************************
519 * FormatMessage16 (USER.606)
521 DWORD WINAPI FormatMessage16(
522 DWORD dwFlags,
523 LPCVOID lpSource,
524 WORD dwMessageId,
525 WORD dwLanguageId,
526 LPSTR lpBuffer,
527 WORD nSize,
528 LPDWORD args /* va_list *args */
530 return FormatMessage32A(dwFlags, lpSource, (DWORD)dwMessageId, (DWORD)dwLanguageId, lpBuffer, (DWORD)nSize, args);
533 /***********************************************************************
534 * FormatMessage32A (KERNEL32.138)
535 * FIXME: missing wrap,FROM_SYSTEM message-loading,
537 DWORD WINAPI FormatMessage32A(
538 DWORD dwFlags,
539 LPCVOID lpSource,
540 DWORD dwMessageId,
541 DWORD dwLanguageId,
542 LPSTR lpBuffer,
543 DWORD nSize,
544 LPDWORD args /* va_list *args */
546 #ifdef __i386__
547 /* This implementation is completely dependant on the format of the va_list on x86 CPUs */
548 LPSTR target,t;
549 DWORD talloced;
550 LPSTR from,f;
551 DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
552 DWORD nolinefeed = 0;
554 TRACE(resource, "(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
555 dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args);
556 if (width)
557 FIXME(resource,"line wrapping not supported.\n");
558 from = NULL;
559 if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
560 from = HEAP_strdupA( GetProcessHeap(), 0, (LPSTR)lpSource);
561 if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) {
562 from = HeapAlloc( GetProcessHeap(),0,200 );
563 sprintf(from,"Systemmessage, messageid = 0x%08lx\n",dwMessageId);
565 if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) {
566 INT32 bufsize;
568 dwMessageId &= 0xFFFF;
569 bufsize=LoadMessage32A((HMODULE32)lpSource,dwMessageId,dwLanguageId,NULL,100);
570 if (bufsize) {
571 from = HeapAlloc( GetProcessHeap(), 0, bufsize + 1 );
572 LoadMessage32A((HMODULE32)lpSource,dwMessageId,dwLanguageId,from,bufsize+1);
575 target = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100);
576 t = target;
577 talloced= 100;
579 #define ADD_TO_T(c) \
580 *t++=c;\
581 if (t-target == talloced) {\
582 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
583 t = target+talloced;\
584 talloced*=2;\
587 if (from) {
588 f=from;
589 while (*f && !nolinefeed) {
590 if (*f=='%') {
591 int insertnr;
592 char *fmtstr,*sprintfbuf,*x,*lastf;
593 DWORD *argliststart;
595 fmtstr = NULL;
596 lastf = f;
597 f++;
598 if (!*f) {
599 ADD_TO_T('%');
600 continue;
602 switch (*f) {
603 case '1':case '2':case '3':case '4':case '5':
604 case '6':case '7':case '8':case '9':
605 insertnr=*f-'0';
606 switch (f[1]) {
607 case '0':case '1':case '2':case '3':
608 case '4':case '5':case '6':case '7':
609 case '8':case '9':
610 f++;
611 insertnr=insertnr*10+*f-'0';
612 f++;
613 break;
614 default:
615 f++;
616 break;
618 if (*f=='!') {
619 f++;
620 if (NULL!=(x=strchr(f,'!'))) {
621 *x='\0';
622 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f)+2);
623 sprintf(fmtstr,"%%%s",f);
624 f=x+1;
625 } else {
626 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f));
627 sprintf(fmtstr,"%%%s",f);
628 f+=strlen(f); /*at \0*/
630 } else
631 if(!args)
632 break;
633 else
634 fmtstr=HEAP_strdupA(GetProcessHeap(),0,"%s");
635 if (args) {
636 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
637 argliststart=args+insertnr-1;
638 else
639 argliststart=(*(DWORD**)args)+insertnr-1;
641 if (fmtstr[strlen(fmtstr)-1]=='s')
642 sprintfbuf=HeapAlloc(GetProcessHeap(),0,strlen((LPSTR)argliststart[0])+1);
643 else
644 sprintfbuf=HeapAlloc(GetProcessHeap(),0,100);
646 /* CMF - This makes a BIG assumption about va_list */
647 wvsprintf32A(sprintfbuf, fmtstr, (va_list) argliststart);
648 x=sprintfbuf;
649 while (*x) {
650 ADD_TO_T(*x++);
652 HeapFree(GetProcessHeap(),0,sprintfbuf);
653 } else {
654 /* NULL args - copy formatstr
655 * (probably wrong)
657 while ((lastf<f)&&(*lastf)) {
658 ADD_TO_T(*lastf++);
661 HeapFree(GetProcessHeap(),0,fmtstr);
662 break;
663 case 'n':
664 /* FIXME: perhaps add \r too? */
665 ADD_TO_T('\n');
666 f++;
667 break;
668 case '0':
669 nolinefeed=1;
670 f++;
671 break;
672 default:ADD_TO_T(*f++)
673 break;
676 } else {
677 ADD_TO_T(*f++)
680 *t='\0';
682 if (!nolinefeed) {
683 /* add linefeed */
684 if(t==target || t[-1]!='\n')
685 ADD_TO_T('\n'); /* FIXME: perhaps add \r too? */
687 talloced = strlen(target)+1;
688 if (nSize && talloced<nSize) {
689 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
691 TRACE(resource,"-- %s\n",debugstr_a(target));
692 if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
693 /* nSize is the MINIMUM size */
694 *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc32(GMEM_ZEROINIT,talloced);
695 memcpy(*(LPSTR*)lpBuffer,target,talloced);
696 } else
697 strncpy(lpBuffer,target,nSize);
698 HeapFree(GetProcessHeap(),0,target);
699 if (from) HeapFree(GetProcessHeap(),0,from);
700 return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
701 strlen(*(LPSTR*)lpBuffer):
702 strlen(lpBuffer);
703 #else
704 return 0;
705 #endif /* __i386__ */
707 #undef ADD_TO_T
710 /***********************************************************************
711 * FormatMessage32W (KERNEL32.138)
713 DWORD WINAPI FormatMessage32W(
714 DWORD dwFlags,
715 LPCVOID lpSource,
716 DWORD dwMessageId,
717 DWORD dwLanguageId,
718 LPWSTR lpBuffer,
719 DWORD nSize,
720 LPDWORD args /* va_list *args */
722 #ifdef __i386__
723 /* This implementation is completely dependant on the format of the va_list on x86 CPUs */
724 LPSTR target,t;
725 DWORD talloced;
726 LPSTR from,f;
727 DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
728 DWORD nolinefeed = 0;
730 TRACE(resource, "(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
731 dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args);
732 if (width)
733 FIXME(resource,"line wrapping not supported.\n");
734 from = NULL;
735 if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
736 from = HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)lpSource);
737 if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) {
738 /* gather information from system message tables ... */
739 from = HeapAlloc( GetProcessHeap(),0,200 );
740 sprintf(from,"Systemmessage, messageid = 0x%08lx\n",dwMessageId);
742 if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) {
743 INT32 bufsize;
745 dwMessageId &= 0xFFFF;
746 bufsize=LoadMessage32A((HMODULE32)lpSource,dwMessageId,dwLanguageId,NULL,100);
747 if (bufsize)
749 from = HeapAlloc( GetProcessHeap(), 0, bufsize + 1 );
750 LoadMessage32A((HMODULE32)lpSource,dwMessageId,dwLanguageId,from,bufsize+1);
753 target = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100 );
754 t = target;
755 talloced= 100;
757 #define ADD_TO_T(c) \
758 *t++=c;\
759 if (t-target == talloced) {\
760 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
761 t = target+talloced;\
762 talloced*=2;\
765 if (from) {
766 f=from;
767 while (*f && !nolinefeed) {
768 if (*f=='%') {
769 int insertnr;
770 char *fmtstr,*sprintfbuf,*x;
771 DWORD *argliststart;
773 fmtstr = NULL;
774 f++;
775 if (!*f) {
776 ADD_TO_T('%');
777 continue;
779 switch (*f) {
780 case '1':case '2':case '3':case '4':case '5':
781 case '6':case '7':case '8':case '9':
782 insertnr=*f-'0';
783 switch (f[1]) {
784 case '0':case '1':case '2':case '3':
785 case '4':case '5':case '6':case '7':
786 case '8':case '9':
787 f++;
788 insertnr=insertnr*10+*f-'0';
789 f++;
790 break;
791 default:
792 f++;
793 break;
795 if (*f=='!') {
796 f++;
797 if (NULL!=(x=strchr(f,'!')))
799 *x='\0';
800 fmtstr=HeapAlloc( GetProcessHeap(), 0, strlen(f)+2);
801 sprintf(fmtstr,"%%%s",f);
802 f=x+1;
803 } else {
804 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f));
805 sprintf(fmtstr,"%%%s",f);
806 f+=strlen(f); /*at \0*/
808 } else
809 if(!args)
810 break;
811 else
812 fmtstr=HEAP_strdupA( GetProcessHeap(),0,"%s");
813 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
814 argliststart=args+insertnr-1;
815 else
816 argliststart=(*(DWORD**)args)+insertnr-1;
818 if (fmtstr[strlen(fmtstr)-1]=='s') {
819 DWORD xarr[3];
821 xarr[0]=(DWORD)HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)(*(argliststart+0)));
822 /* possible invalid pointers */
823 xarr[1]=*(argliststart+1);
824 xarr[2]=*(argliststart+2);
825 sprintfbuf=HeapAlloc(GetProcessHeap(),0,lstrlen32W((LPWSTR)argliststart[0])*2+1);
827 /* CMF - This makes a BIG assumption about va_list */
828 vsprintf(sprintfbuf, fmtstr, (va_list) xarr);
829 } else {
830 sprintfbuf=HeapAlloc(GetProcessHeap(),0,100);
832 /* CMF - This makes a BIG assumption about va_list */
833 wvsprintf32A(sprintfbuf, fmtstr, (va_list) argliststart);
835 x=sprintfbuf;
836 while (*x) {
837 ADD_TO_T(*x++);
839 HeapFree(GetProcessHeap(),0,sprintfbuf);
840 HeapFree(GetProcessHeap(),0,fmtstr);
841 break;
842 case 'n':
843 /* FIXME: perhaps add \r too? */
844 ADD_TO_T('\n');
845 f++;
846 break;
847 case '0':
848 nolinefeed=1;
849 f++;
850 break;
851 default:ADD_TO_T(*f++)
852 break;
855 } else {
856 ADD_TO_T(*f++)
859 *t='\0';
861 if (!nolinefeed) {
862 /* add linefeed */
863 if(t==target || t[-1]!='\n')
864 ADD_TO_T('\n'); /* FIXME: perhaps add \r too? */
866 talloced = strlen(target)+1;
867 if (nSize && talloced<nSize)
868 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
869 if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
870 /* nSize is the MINIMUM size */
871 *((LPVOID*)lpBuffer) = (LPVOID)LocalAlloc32(GMEM_ZEROINIT,talloced*2+2);
872 lstrcpynAtoW(*(LPWSTR*)lpBuffer,target,talloced);
873 } else
874 lstrcpynAtoW(lpBuffer,target,nSize);
875 HeapFree(GetProcessHeap(),0,target);
876 if (from) HeapFree(GetProcessHeap(),0,from);
877 return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
878 lstrlen32W(*(LPWSTR*)lpBuffer):
879 lstrlen32W(lpBuffer);
880 #else
881 return 0;
882 #endif /* __i386__ */
884 #undef ADD_TO_T