4 * Copyright 1993 Yngvi Sigurjonsson (yngvi@hafro.is)
5 * Copyright 1996 Marcus Meissner
15 #include "winnt.h" /* HEAP_ macros */
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
)
40 /* IsCharUpper USER 435 */
41 BOOL16
IsCharUpper16(CHAR ch
)
46 /* IsCharLower USER 436 */
47 BOOL16
IsCharLower16(CHAR 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
))
64 for (s
= PTR_SEG_TO_LIN(strOrChar
); *s
; s
++) *s
= toupper(*s
);
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
);
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
))
93 for (s
= PTR_SEG_TO_LIN( strOrChar
); *s
; s
++) *s
= tolower( *s
);
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
);
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 * OutputDebugString (KERNEL.115)
132 void OutputDebugString( LPCSTR str
)
135 char *p
, *buffer
= HeapAlloc( GetProcessHeap(), 0, strlen(str
)+1 );
137 for (p
= buffer
; *str
; str
++) if (*str
!= '\r') *p
++ = *str
;
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 * CharNext32A (USER32.28)
150 LPSTR
CharNext32A( LPCSTR ptr
)
152 if (!*ptr
) return (LPSTR
)ptr
;
153 if (IsDBCSLeadByte32( *ptr
)) return (LPSTR
)(ptr
+ 2);
154 return (LPSTR
)(ptr
+ 1);
158 /***********************************************************************
159 * CharNextEx32A (USER32.29)
161 LPSTR
CharNextEx32A( WORD codepage
, LPCSTR ptr
, DWORD flags
)
163 if (!*ptr
) return (LPSTR
)ptr
;
164 if (IsDBCSLeadByteEx( codepage
, *ptr
)) return (LPSTR
)(ptr
+ 2);
165 return (LPSTR
)(ptr
+ 1);
169 /***********************************************************************
170 * CharNextExW (USER32.30)
172 LPWSTR
CharNextEx32W(WORD codepage
,LPCWSTR x
,DWORD flags
)
174 /* FIXME: add DBCS / codepage stuff */
175 if (*x
) return (LPWSTR
)(x
+1);
176 else return (LPWSTR
)x
;
179 /***********************************************************************
180 * CharNextW (USER32.31)
182 LPWSTR
CharNext32W(LPCWSTR x
)
184 if (*x
) return (LPWSTR
)(x
+1);
185 else return (LPWSTR
)x
;
188 /***********************************************************************
189 * CharPrev32A (USER32.32)
191 LPSTR
CharPrev32A( LPCSTR start
, LPCSTR ptr
)
193 while (*start
&& (start
< ptr
))
195 LPCSTR next
= CharNext32A( start
);
196 if (next
>= ptr
) break;
203 /***********************************************************************
204 * CharPrevEx32A (USER32.33)
206 LPSTR
CharPrevEx32A( WORD codepage
, LPCSTR start
, LPCSTR ptr
, DWORD flags
)
208 while (*start
&& (start
< ptr
))
210 LPCSTR next
= CharNextEx32A( codepage
, start
, flags
);
211 if (next
> ptr
) break;
218 /***********************************************************************
219 * CharPrevExW (USER32.34)
221 LPWSTR
CharPrevEx32W(WORD codepage
,LPCWSTR start
,LPCWSTR x
,DWORD flags
)
223 /* FIXME: add DBCS / codepage stuff */
224 if (x
>start
) return (LPWSTR
)(x
-1);
225 else return (LPWSTR
)x
;
228 /***********************************************************************
229 * CharPrevW (USER32.35)
231 LPWSTR
CharPrev32W(LPCWSTR start
,LPCWSTR x
)
233 if (x
>start
) return (LPWSTR
)(x
-1);
234 else return (LPWSTR
)x
;
237 /***********************************************************************
238 * CharLowerA (USER32.24)
239 * FIXME: handle current locale
241 LPSTR
CharLower32A(LPSTR x
)
255 else return (LPSTR
)tolower(LOWORD(x
));
258 /***********************************************************************
259 * CharLowerBuffA (USER32.25)
260 * FIXME: handle current locale
262 DWORD
CharLowerBuff32A(LPSTR x
,DWORD buflen
)
266 while (*x
&& (buflen
--))
275 /***********************************************************************
276 * CharLowerBuffW (USER32.26)
277 * FIXME: handle current locale
279 DWORD
CharLowerBuff32W(LPWSTR x
,DWORD buflen
)
283 while (*x
&& (buflen
--))
292 /***********************************************************************
293 * CharLowerW (USER32.27)
294 * FIXME: handle current locale
296 LPWSTR
CharLower32W(LPWSTR x
)
308 else return (LPWSTR
)tolower(LOWORD(x
));
311 /***********************************************************************
312 * CharUpper32A (USER32.40)
313 * FIXME: handle current locale
315 LPSTR
CharUpper32A(LPSTR x
)
327 else return (LPSTR
)toupper(LOWORD(x
));
330 /***********************************************************************
331 * CharUpperBuffA (USER32.41)
332 * FIXME: handle current locale
334 DWORD
CharUpperBuff32A(LPSTR x
,DWORD buflen
)
338 while (*x
&& (buflen
--))
347 /***********************************************************************
348 * CharUpperBuffW (USER32.42)
349 * FIXME: handle current locale
351 DWORD
CharUpperBuff32W(LPWSTR x
,DWORD buflen
)
355 while (*x
&& (buflen
--))
364 /***********************************************************************
365 * CharUpperW (USER32.43)
366 * FIXME: handle current locale
368 LPWSTR
CharUpper32W(LPWSTR x
)
380 else return (LPWSTR
)toupper(LOWORD(x
));
383 /***********************************************************************
384 * IsCharAlphaA (USER32.330)
385 * FIXME: handle current locale
387 BOOL32
IsCharAlpha32A(CHAR x
)
392 /***********************************************************************
393 * IsCharAlphaNumericA (USER32.331)
394 * FIXME: handle current locale
396 BOOL32
IsCharAlphaNumeric32A(CHAR x
)
401 /***********************************************************************
402 * IsCharAlphaNumericW (USER32.332)
403 * FIXME: handle current locale
405 BOOL32
IsCharAlphaNumeric32W(WCHAR x
)
410 /***********************************************************************
411 * IsCharAlphaW (USER32.333)
412 * FIXME: handle current locale
414 BOOL32
IsCharAlpha32W(WCHAR x
)
419 /***********************************************************************
420 * IsCharLower32A (USER32.334)
421 * FIXME: handle current locale
423 BOOL32
IsCharLower32A(CHAR x
)
428 /***********************************************************************
429 * IsCharLower32W (USER32.335)
430 * FIXME: handle current locale
432 BOOL32
IsCharLower32W(WCHAR x
)
437 /***********************************************************************
438 * IsCharUpper32A (USER32.336)
439 * FIXME: handle current locale
441 BOOL32
IsCharUpper32A(CHAR x
)
446 /***********************************************************************
447 * IsCharUpper32W (USER32.337)
448 * FIXME: handle current locale
450 BOOL32
IsCharUpper32W(WCHAR x
)
455 /***********************************************************************
456 * FormatMessageA (KERNEL32.138) Library Version
457 * FIXME: missing wrap,FROM_SYSTEM message-loading,
467 LPDWORD args
/* va_list *args */
472 DWORD width
= dwFlags
& FORMAT_MESSAGE_MAX_WIDTH_MASK
;
473 DWORD nolinefeed
= 0;
475 dprintf_resource(stddeb
,
476 "FormatMessage32A(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
477 dwFlags
,lpSource
,dwMessageId
,dwLanguageId
,lpBuffer
,nSize
,args
480 fprintf(stdnimp
," - line wrapping not supported.\n");
482 if (dwFlags
& FORMAT_MESSAGE_FROM_STRING
)
483 from
= HEAP_strdupA( GetProcessHeap(), 0, (LPSTR
)lpSource
);
484 if (dwFlags
& FORMAT_MESSAGE_FROM_SYSTEM
) {
485 /* gather information from system message tables ... */
486 fprintf(stdnimp
," - FORMAT_MESSAGE_FROM_SYSTEM not implemented.\n");
488 if (dwFlags
& FORMAT_MESSAGE_FROM_HMODULE
) {
491 dwMessageId
&= 0xFFFF;
492 bufsize
=LoadMessage32A(0,dwMessageId
,dwLanguageId
,NULL
,100);
494 from
= HeapAlloc( GetProcessHeap(), 0, bufsize
+ 1 );
495 LoadMessage32A(0,dwMessageId
,dwLanguageId
,from
,bufsize
+1);
498 target
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, 100);
502 #define ADD_TO_T(c) \
504 if (t-target == talloced) {\
505 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
506 t = target+talloced;\
515 char *fmtstr
,*sprintfbuf
,*x
;
525 case '1':case '2':case '3':case '4':case '5':
526 case '6':case '7':case '8':case '9':
529 case '0':case '1':case '2':case '3':
530 case '4':case '5':case '6':case '7':
533 insertnr
=insertnr
*10+*f
-'0';
542 if (NULL
!=(x
=strchr(f
,'!'))) {
544 fmtstr
=HeapAlloc(GetProcessHeap(),0,strlen(f
)+2);
545 sprintf(fmtstr
,"%%%s",f
);
549 fmtstr
=HEAP_strdupA(GetProcessHeap(),0,"%s");
550 if (dwFlags
& FORMAT_MESSAGE_ARGUMENT_ARRAY
)
551 argliststart
=args
+insertnr
-1;
553 /* FIXME: not sure that this is
554 * correct for unix-c-varargs.
556 argliststart
=((DWORD
*)&args
)+insertnr
-1;
558 if (fmtstr
[strlen(fmtstr
)]=='s')
559 sprintfbuf
=HeapAlloc(GetProcessHeap(),0,strlen((LPSTR
)argliststart
[0])+1);
561 sprintfbuf
=HeapAlloc(GetProcessHeap(),0,100);
562 vsprintf(sprintfbuf
,fmtstr
,argliststart
);
567 HeapFree(GetProcessHeap(),0,sprintfbuf
);
568 HeapFree(GetProcessHeap(),0,fmtstr
);
571 /* FIXME: perhaps add \r too? */
579 default:ADD_TO_T(*f
++)
589 if (!nolinefeed
&& t
[-1]!='\n')
591 talloced
= strlen(target
)+1;
592 if (nSize
&& talloced
<nSize
) {
593 target
= (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,target
,nSize
);
595 if (dwFlags
& FORMAT_MESSAGE_ALLOCATE_BUFFER
) {
596 /* nSize is the MINIMUM size */
597 *((LPVOID
*)lpBuffer
) = (LPVOID
)LocalAlloc32(GMEM_ZEROINIT
,talloced
);
598 memcpy(*(LPSTR
*)lpBuffer
,target
,talloced
);
600 strncpy(lpBuffer
,target
,nSize
);
601 HeapFree(GetProcessHeap(),0,target
);
602 if (from
) HeapFree(GetProcessHeap(),0,from
);
603 return (dwFlags
& FORMAT_MESSAGE_ALLOCATE_BUFFER
) ?
604 strlen(*(LPSTR
*)lpBuffer
):
609 /***********************************************************************
610 * FormatMessageA (KERNEL32.138) Emulator Version
613 WIN32_FormatMessage32A(DWORD
*args
) {
614 DWORD dwFlags
= args
[0];
615 LPCVOID lpSource
= (LPCVOID
)args
[1];
616 DWORD dwMessageId
= args
[2];
617 DWORD dwLanguageId
= args
[3];
618 LPSTR lpBuffer
= (LPSTR
)args
[4];
619 DWORD nSize
= args
[5];
622 /* convert possible varargs to an argument array look-a-like */
624 if (dwFlags
& FORMAT_MESSAGE_ARGUMENT_ARRAY
) {
625 xargs
=(DWORD
*)args
[6];
627 /* args[6] is a pointer to a pointer to the start of
628 * a list of arguments.
631 xargs
=(DWORD
*)(((DWORD
*)args
[6])[0]);
634 dwFlags
|=FORMAT_MESSAGE_ARGUMENT_ARRAY
;
636 return FormatMessage32A(
655 LPDWORD args
/* va_list *args */
660 DWORD width
= dwFlags
& FORMAT_MESSAGE_MAX_WIDTH_MASK
;
661 DWORD nolinefeed
= 0;
663 dprintf_resource(stddeb
,
664 "FormatMessage32A(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n",
665 dwFlags
,lpSource
,dwMessageId
,dwLanguageId
,lpBuffer
,nSize
,args
668 fprintf(stdnimp
," - line wrapping not supported.\n");
670 if (dwFlags
& FORMAT_MESSAGE_FROM_STRING
)
671 from
= HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR
)lpSource
);
672 if (dwFlags
& FORMAT_MESSAGE_FROM_SYSTEM
) {
673 /* gather information from system message tables ... */
674 fprintf(stdnimp
," - FORMAT_MESSAGE_FROM_SYSTEM not implemented.\n");
676 if (dwFlags
& FORMAT_MESSAGE_FROM_HMODULE
) {
679 dwMessageId
&= 0xFFFF;
680 bufsize
=LoadMessage32A(0,dwMessageId
,dwLanguageId
,NULL
,100);
683 from
= HeapAlloc( GetProcessHeap(), 0, bufsize
+ 1 );
684 LoadMessage32A(0,dwMessageId
,dwLanguageId
,from
,bufsize
+1);
687 target
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
, 100 );
691 #define ADD_TO_T(c) \
693 if (t-target == talloced) {\
694 target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
695 t = target+talloced;\
704 char *fmtstr
,*sprintfbuf
,*x
;
714 case '1':case '2':case '3':case '4':case '5':
715 case '6':case '7':case '8':case '9':
718 case '0':case '1':case '2':case '3':
719 case '4':case '5':case '6':case '7':
722 insertnr
=insertnr
*10+*f
-'0';
731 if (NULL
!=(x
=strchr(f
,'!')))
734 fmtstr
=HeapAlloc( GetProcessHeap(), 0, strlen(f
)+2);
735 sprintf(fmtstr
,"%%%s",f
);
739 fmtstr
=HEAP_strdupA( GetProcessHeap(),0,"%s");
740 if (dwFlags
& FORMAT_MESSAGE_ARGUMENT_ARRAY
)
741 argliststart
=args
+insertnr
-1;
743 /* FIXME: not sure that this is
744 * correct for unix-c-varargs.
746 argliststart
=((DWORD
*)&args
)+insertnr
-1;
748 if (fmtstr
[strlen(fmtstr
)]=='s') {
751 xarr
[0]=(DWORD
)HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR
)(*(argliststart
+0)));
752 /* possible invalid pointers */
753 xarr
[1]=*(argliststart
+1);
754 xarr
[2]=*(argliststart
+2);
755 sprintfbuf
=HeapAlloc(GetProcessHeap(),0,lstrlen32W((LPWSTR
)argliststart
[0])*2+1);
756 vsprintf(sprintfbuf
,fmtstr
,xarr
);
758 sprintfbuf
=HeapAlloc(GetProcessHeap(),0,100);
759 vsprintf(sprintfbuf
,fmtstr
,argliststart
);
765 HeapFree(GetProcessHeap(),0,sprintfbuf
);
766 HeapFree(GetProcessHeap(),0,fmtstr
);
769 /* FIXME: perhaps add \r too? */
777 default:ADD_TO_T(*f
++)
787 if (!nolinefeed
&& t
[-1]!='\n')
789 talloced
= strlen(target
)+1;
790 if (nSize
&& talloced
<nSize
)
791 target
= (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,target
,nSize
);
792 if (dwFlags
& FORMAT_MESSAGE_ALLOCATE_BUFFER
) {
793 /* nSize is the MINIMUM size */
794 *((LPVOID
*)lpBuffer
) = (LPVOID
)LocalAlloc32(GMEM_ZEROINIT
,talloced
*2+2);
795 lstrcpynAtoW(*(LPWSTR
*)lpBuffer
,target
,talloced
);
797 lstrcpynAtoW(lpBuffer
,target
,nSize
);
798 HeapFree(GetProcessHeap(),0,target
);
799 if (from
) HeapFree(GetProcessHeap(),0,from
);
800 return (dwFlags
& FORMAT_MESSAGE_ALLOCATE_BUFFER
) ?
801 lstrlen32W(*(LPWSTR
*)lpBuffer
):
802 lstrlen32W(lpBuffer
);
806 /***********************************************************************
807 * FormatMessageA (KERNEL32.138) Emulator Version
810 WIN32_FormatMessage32W(DWORD
*args
) {
811 DWORD dwFlags
= args
[0];
812 LPCVOID lpSource
= (LPCVOID
)args
[1];
813 DWORD dwMessageId
= args
[2];
814 DWORD dwLanguageId
= args
[3];
815 LPWSTR lpBuffer
= (LPWSTR
)args
[4];
816 DWORD nSize
= args
[5];
819 /* convert possible varargs to an argument array look-a-like */
821 if (dwFlags
& FORMAT_MESSAGE_ARGUMENT_ARRAY
) {
822 xargs
=(DWORD
*)args
[6];
824 /* args[6] is a pointer to a pointer to the start of
825 * a list of arguments.
828 xargs
=(DWORD
*)(((DWORD
*)args
[6])[0]);
831 dwFlags
|=FORMAT_MESSAGE_ARGUMENT_ARRAY
;
833 return FormatMessage32W(