4 * Copyright 1993 Yngvi Sigurjonsson (yngvi@hafro.is)
5 * Copyright 1996 Marcus Meissner
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 */
28 #include "winnt.h" /* HEAP_ macros */
32 #include "stackframe.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)
56 /***********************************************************************
57 * IsCharUpper (USER.435)
59 BOOL16 WINAPI IsCharUpper16(CHAR ch)
64 /***********************************************************************
65 * IsCharLower (USER.436)
67 BOOL16 WINAPI IsCharLower16(CHAR 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))
84 for (s = PTR_SEG_TO_LIN(strOrChar); *s; s++) *s = toupper(*s);
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);
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))
113 for (s = PTR_SEG_TO_LIN( strOrChar ); *s; s++) *s = tolower( *s );
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);
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 )
155 char *p, *buffer = HeapAlloc( GetProcessHeap(), 0, strlen(str)+2 );
157 for (p = buffer; *str; str++) if (*str != '\r') *p++ = *str;
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;
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;
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)
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)
308 if (!x) return 0; /* YES */
309 while (*x && (buflen--))
318 /***********************************************************************
319 * CharLowerBuffW (USER32.26)
320 * FIXME: handle current locale
322 DWORD WINAPI CharLowerBuff32W(LPWSTR x,DWORD buflen)
326 if (!x) return 0; /* YES */
327 while (*x && (buflen--))
336 /***********************************************************************
337 * CharLowerW (USER32.27)
338 * FIXME: handle current locale
340 LPWSTR WINAPI CharLower32W(LPWSTR x)
352 else return (LPWSTR)towlower(LOWORD(x));
355 /***********************************************************************
356 * CharUpper32A (USER32.40)
357 * FIXME: handle current locale
359 LPSTR WINAPI CharUpper32A(LPSTR 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)
382 if (!x) return 0; /* YES */
383 while (*x && (buflen--))
392 /***********************************************************************
393 * CharUpperBuffW (USER32.42)
394 * FIXME: handle current locale
396 DWORD WINAPI CharUpperBuff32W(LPWSTR x,DWORD buflen)
400 if (!x) return 0; /* YES */
401 while (*x && (buflen--))
410 /***********************************************************************
411 * CharUpperW (USER32.43)
412 * FIXME: handle current locale
414 LPWSTR WINAPI CharUpper32W(LPWSTR x)
426 else return (LPWSTR)towupper(LOWORD(x));
429 /***********************************************************************
430 * IsCharAlphaA (USER32.330)
431 * FIXME: handle current locale
433 BOOL32 WINAPI IsCharAlpha32A(CHAR x)
438 /***********************************************************************
439 * IsCharAlphaNumericA (USER32.331)
440 * FIXME: handle current locale
442 BOOL32 WINAPI IsCharAlphaNumeric32A(CHAR x)
447 /***********************************************************************
448 * IsCharAlphaNumericW (USER32.332)
449 * FIXME: handle current locale
451 BOOL32 WINAPI IsCharAlphaNumeric32W(WCHAR x)
456 /***********************************************************************
457 * IsCharAlphaW (USER32.333)
458 * FIXME: handle current locale
460 BOOL32 WINAPI IsCharAlpha32W(WCHAR x)
465 /***********************************************************************
466 * IsCharLower32A (USER32.334)
467 * FIXME: handle current locale
469 BOOL32 WINAPI IsCharLower32A(CHAR x)
474 /***********************************************************************
475 * IsCharLower32W (USER32.335)
476 * FIXME: handle current locale
478 BOOL32 WINAPI IsCharLower32W(WCHAR x)
483 /***********************************************************************
484 * IsCharUpper32A (USER32.336)
485 * FIXME: handle current locale
487 BOOL32 WINAPI IsCharUpper32A(CHAR x)
492 /***********************************************************************
493 * IsCharUpper32W (USER32.337)
494 * FIXME: handle current locale
496 BOOL32 WINAPI IsCharUpper32W(WCHAR x)
501 /***********************************************************************
502 * FormatMessage32A (KERNEL32.138)
503 * FIXME: missing wrap,FROM_SYSTEM message-loading,
505 DWORD WINAPI FormatMessage32A(
512 LPDWORD args /* va_list *args */
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
525 fprintf(stdnimp," - line wrapping not supported.\n");
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) {
536 dwMessageId &= 0xFFFF;
537 bufsize=LoadMessage32A((HMODULE32)lpSource,dwMessageId,dwLanguageId,NULL,100);
539 from = HeapAlloc( GetProcessHeap(), 0, bufsize + 1 );
540 LoadMessage32A((HMODULE32)lpSource,dwMessageId,dwLanguageId,from,bufsize+1);
543 target = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100);
547 #define ADD_TO_T(c) \
549 if (t-target == talloced) {\
550 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
551 t = target+talloced;\
560 char *fmtstr,*sprintfbuf,*x,*lastf;
571 case '1':case '2':case '3':case '4':case '5':
572 case '6':case '7':case '8':case '9':
575 case '0':case '1':case '2':case '3':
576 case '4':case '5':case '6':case '7':
579 insertnr=insertnr*10+*f-'0';
588 if (NULL!=(x=strchr(f,'!'))) {
590 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f)+2);
591 sprintf(fmtstr,"%%%s",f);
594 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f));
595 sprintf(fmtstr,"%%%s",f);
596 f+=strlen(f); /*at \0*/
599 fmtstr=HEAP_strdupA(GetProcessHeap(),0,"%s");
601 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
602 argliststart=args+insertnr-1;
604 argliststart=(*(DWORD**)args)+insertnr-1;
606 if (fmtstr[strlen(fmtstr)]=='s')
607 sprintfbuf=HeapAlloc(GetProcessHeap(),0,strlen((LPSTR)argliststart[0])+1);
609 sprintfbuf=HeapAlloc(GetProcessHeap(),0,100);
611 /* CMF - This makes a BIG assumption about va_list */
612 vsprintf(sprintfbuf, fmtstr, (va_list) argliststart);
617 HeapFree(GetProcessHeap(),0,sprintfbuf);
619 /* NULL args - copy formatstr
626 HeapFree(GetProcessHeap(),0,fmtstr);
629 /* FIXME: perhaps add \r too? */
637 default:ADD_TO_T(*f++)
647 if (!nolinefeed && t[-1]!='\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);
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):
668 /***********************************************************************
669 * FormatMessage32W (KERNEL32.138)
671 DWORD WINAPI FormatMessage32W(
678 LPDWORD args /* va_list *args */
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
691 fprintf(stdnimp," - line wrapping not supported.\n");
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) {
703 dwMessageId &= 0xFFFF;
704 bufsize=LoadMessage32A((HMODULE32)lpSource,dwMessageId,dwLanguageId,NULL,100);
707 from = HeapAlloc( GetProcessHeap(), 0, bufsize + 1 );
708 LoadMessage32A((HMODULE32)lpSource,dwMessageId,dwLanguageId,from,bufsize+1);
711 target = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100 );
715 #define ADD_TO_T(c) \
717 if (t-target == talloced) {\
718 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
719 t = target+talloced;\
728 char *fmtstr,*sprintfbuf,*x;
738 case '1':case '2':case '3':case '4':case '5':
739 case '6':case '7':case '8':case '9':
742 case '0':case '1':case '2':case '3':
743 case '4':case '5':case '6':case '7':
746 insertnr=insertnr*10+*f-'0';
755 if (NULL!=(x=strchr(f,'!')))
758 fmtstr=HeapAlloc( GetProcessHeap(), 0, strlen(f)+2);
759 sprintf(fmtstr,"%%%s",f);
762 fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f));
763 sprintf(fmtstr,"%%%s",f);
764 f+=strlen(f); /*at \0*/
767 fmtstr=HEAP_strdupA( GetProcessHeap(),0,"%s");
768 if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
769 argliststart=args+insertnr-1;
771 argliststart=(*(DWORD**)args)+insertnr-1;
773 if (fmtstr[strlen(fmtstr)]=='s') {
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);
785 sprintfbuf=HeapAlloc(GetProcessHeap(),0,100);
787 /* CMF - This makes a BIG assumption about va_list */
788 vsprintf(sprintfbuf, fmtstr, (va_list) argliststart);
794 HeapFree(GetProcessHeap(),0,sprintfbuf);
795 HeapFree(GetProcessHeap(),0,fmtstr);
798 /* FIXME: perhaps add \r too? */
806 default:ADD_TO_T(*f++)
816 if (!nolinefeed && t[-1]!='\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);
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);