Nevermind.

Regression found. Rolling back the last change.
Jim's adaption of the WINE code was better.

svn path=/trunk/; revision=6532
This commit is contained in:
Steven Edwards 2003-11-05 20:42:02 +00:00
parent eaa7c16f59
commit 7bee3f3c72

View file

@ -1,3 +1,8 @@
/* $Id: errormsg.c,v 1.10 2003/11/05 20:42:02 sedwards Exp $
*
* reactos/lib/kernel32/misc/errormsg.c
*
*/
/* /*
* FormatMessage implementation * FormatMessage implementation
* *
@ -18,28 +23,59 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
/* $Id: errormsg.c,v 1.9 2003/11/05 20:32:07 sedwards Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel32
* PURPOSE: Format Message
* FILE: lib/user32/controls/static.c
* PROGRAMER: Steven Edwards lib/kernel32/misc/errormsg.c
* REVISION HISTORY: 2003/11/05 Created
* NOTES: Adapted from Wine
*/
#include <ddk/ntddk.h> #include <ddk/ntddk.h>
// #define NDEBUG
#include <kernel32/kernel32.h> #include <kernel32/kernel32.h>
#include <kernel32/error.h> #include <kernel32/error.h>
#include <stdio.h>
#include <string.h>
#include <wine/unicode.h>
/* Wine porting stuff */ #define USE_WINE_PORT
#ifdef USE_WINE_PORT
//#define NDEBUG
//#include <ntdll/ntdll.h>
//#define DPRINTF DPRINT
//#define ERR DPRINT
//#define SetLastError(x)
//#define WARN DPRINT
#define TRACE DPRINT #define TRACE DPRINT
#define FIXME DPRINT #define FIXME DPRINT
//#define MAKEINTRESOURCE(i) (LPTSTR) ((DWORD) ((WORD) (i)))
//#define MAKEINTRESOURCEA(i) (LPTSTR) ((DWORD) ((WORD) (i)))
//#define MAKEINTRESOURCEW(i) (LPTSTR) ((DWORD) ((WORD) (i)))
//#define MAKEINTRESOURCEA(i) (LPSTR)((ULONG_PTR)((WORD)(i)))
//#define MAKEINTRESOURCEW(i) (LPWSTR)((ULONG_PTR)((WORD)(i)))
//#define MAKEINTRESOURCE WINELIB_NAME_AW(MAKEINTRESOURCE)
int HEAP_strdupWtoA(HANDLE hHeap, int flags, LPWSTR lpSource)
{
return 0;
}
/* INTERNAL */
//#include "config.h"
#include <stdio.h>
#include <string.h>
//#include "windef.h"
//#include "winbase.h"
//#include "winerror.h"
//#include "winuser.h"
//#include "winnls.h"
//#include "wine/unicode.h"
//#include "heap.h"
//#include "wine/debug.h"
//WINE_DEFAULT_DEBUG_CHANNEL(resource);
typedef struct tagMESSAGE_RESOURCE_ENTRY { typedef struct tagMESSAGE_RESOURCE_ENTRY {
WORD Length; WORD Length;
WORD Flags; WORD Flags;
@ -58,39 +94,13 @@ typedef struct tagMESSAGE_RESOURCE_DATA {
MESSAGE_RESOURCE_BLOCK Blocks[ 1 ]; MESSAGE_RESOURCE_BLOCK Blocks[ 1 ];
} MESSAGE_RESOURCE_DATA,*PMESSAGE_RESOURCE_DATA; } MESSAGE_RESOURCE_DATA,*PMESSAGE_RESOURCE_DATA;
/* These are needed so that we can call the functions from inside kernel itself */
LPVOID WINAPI HeapAlloc( HANDLE heap, DWORD flags, SIZE_T size ) //#define RT_RCDATAA MAKEINTRESOURCEA(10)
{ //#define RT_RCDATAW MAKEINTRESOURCEW(10)
return RtlAllocateHeap( heap, flags, size ); ////#define RT_RCDATA WINELIB_NAME_AW(RT_RCDATA)
} //#define RT_MESSAGETABLEA MAKEINTRESOURCEA(11)
//#define RT_MESSAGETABLEW MAKEINTRESOURCEW(11)
BOOL WINAPI HeapFree( HANDLE heap, DWORD flags, LPVOID ptr ) ////#define RT_MESSAGETABLE WINELIB_NAME_AW(RT_MESSAGETABLE)
{
return RtlFreeHeap( heap, flags, ptr );
}
LPVOID WINAPI HeapReAlloc( HANDLE heap, DWORD flags, LPVOID ptr, SIZE_T size )
{
return RtlReAllocateHeap( heap, flags, ptr, size );
}
/* strdup macros */
/* DO NOT USE IT!! it will go away soon */
inline static LPSTR HEAP_strdupWtoA( HANDLE heap, DWORD flags, LPCWSTR str )
{
LPSTR ret;
INT len;
if (!str) return NULL;
len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
ret = HeapAlloc( heap, flags, len );
if(ret) WideCharToMultiByte( CP_ACP, 0, str, -1, ret, len, NULL, NULL );
return ret;
}
/* End of WINE porting Code */
/* Messages...used by FormatMessage32* (KERNEL32.something) /* Messages...used by FormatMessage32* (KERNEL32.something)
* *
@ -101,57 +111,85 @@ inline static LPSTR HEAP_strdupWtoA( HANDLE heap, DWORD flags, LPCWSTR str )
* start: * start:
* 0: DWORD nrofentries * 0: DWORD nrofentries
* nrofentries * subentry: * nrofentries * subentry:
* 0: DWORD firstentry * 0: DWORD firstentry
* 4: DWORD lastentry * 4: DWORD lastentry
* 8: DWORD offset from start to the stringentries * 8: DWORD offset from start to the stringentries
* *
* (lastentry-firstentry) * stringentry: * (lastentry-firstentry) * stringentry:
* 0: WORD len (0 marks end) [ includes the 4 byte header length ] * 0: WORD len (0 marks end) [ includes the 4 byte header length ]
* 2: WORD flags * 2: WORD flags
* 4: CHAR[len-4] * 4: CHAR[len-4]
* (stringentry i of a subentry refers to the ID 'firstentry+i') * (stringentry i of a subentry refers to the ID 'firstentry+i')
* *
* Yes, ANSI strings in win32 resources. Go figure. * Yes, ANSI strings in win32 resources. Go figure.
*/ */
/********************************************************************** /**********************************************************************
* load_messageA (internal) * load_messageA (internal)
*/ */
static INT load_messageA( HMODULE instance, UINT id, WORD lang, static INT load_messageA( HMODULE instance, UINT id, WORD lang,
LPSTR buffer, INT buflen ) LPSTR buffer, INT buflen )
{ {
const MESSAGE_RESOURCE_ENTRY *mre; HGLOBAL hmem;
int i,slen; HRSRC hrsrc;
PMESSAGE_RESOURCE_DATA mrd;
PMESSAGE_RESOURCE_BLOCK mrb;
PMESSAGE_RESOURCE_ENTRY mre;
int i,slen;
TRACE("instance = %08lx, id = %08lx, buffer = %p, length = %ld\n", (DWORD)instance, (DWORD)id, buffer, (DWORD)buflen); //TRACE("instance = %08lx, id = %08lx, buffer = %p, length = %ld\n", (DWORD)instance, (DWORD)id, buffer, (DWORD)buflen);
//if (RtlFindMessage( instance, RT_MESSAGETABLE, lang, id, &mre ) != STATUS_SUCCESS) return 0; /*FIXME: I am not sure about the '1' ... But I've only seen those entries*/
hrsrc = FindResourceExW(instance,RT_MESSAGETABLEW,(LPWSTR)1,lang);
if (!hrsrc) return 0;
hmem = LoadResource( instance, hrsrc );
if (!hmem) return 0;
mrd = (PMESSAGE_RESOURCE_DATA)LockResource(hmem);
mre = NULL;
mrb = &(mrd->Blocks[0]);
for (i=mrd->NumberOfBlocks;i--;) {
if ((id>=mrb->LowId) && (id<=mrb->HighId)) {
mre = (PMESSAGE_RESOURCE_ENTRY)(((char*)mrd)+mrb->OffsetToEntries);
id -= mrb->LowId;
break;
}
mrb++;
}
if (!mre)
return 0;
for (i=id;i--;) {
if (!mre->Length)
return 0;
mre = (PMESSAGE_RESOURCE_ENTRY)(((char*)mre)+mre->Length);
}
slen=mre->Length; slen=mre->Length;
TRACE(" - strlen=%d\n",slen); //TRACE(" - strlen=%d\n",slen);
i = min(buflen - 1, slen); i = min(buflen - 1, slen);
if (buffer == NULL) if (buffer == NULL)
return slen; return slen;
if (i>0) { if (i>0) {
if (mre->Flags & MESSAGE_RESOURCE_UNICODE) if (mre->Flags & MESSAGE_RESOURCE_UNICODE)
WideCharToMultiByte( CP_ACP, 0, (LPWSTR)mre->Text, -1, buffer, i, NULL, NULL ); WideCharToMultiByte( CP_ACP, 0, (LPWSTR)mre->Text, -1, buffer, i, NULL, NULL );
else else
lstrcpynA(buffer, (LPSTR)mre->Text, i); lstrcpynA(buffer, (LPSTR)mre->Text, i);
buffer[i]=0; buffer[i]=0;
} else { } else {
if (buflen>1) { if (buflen>1) {
buffer[0]=0; buffer[0]=0;
return 0; return 0;
} }
}
if (buffer) {
//TRACE("'%s' copied !\n", buffer);
TRACE("'%s'\n", buffer);
} }
if (buffer)
TRACE("'%s' copied !\n", buffer);
return i; return i;
} }
#if 0 /* FIXME */ #if 0 /* FIXME */
/********************************************************************** /**********************************************************************
* load_messageW (internal) * load_messageW (internal)
*/ */
static INT load_messageW( HMODULE instance, UINT id, WORD lang, static INT load_messageW( HMODULE instance, UINT id, WORD lang,
LPWSTR buffer, INT buflen ) LPWSTR buffer, INT buflen )
@ -159,15 +197,15 @@ static INT load_messageW( HMODULE instance, UINT id, WORD lang,
INT retval; INT retval;
LPSTR buffer2 = NULL; LPSTR buffer2 = NULL;
if (buffer && buflen) if (buffer && buflen)
buffer2 = HeapAlloc( GetProcessHeap(), 0, buflen ); buffer2 = HeapAlloc( GetProcessHeap(), 0, buflen );
retval = load_messageA(instance,id,lang,buffer2,buflen); retval = load_messageA(instance,id,lang,buffer2,buflen);
if (buffer) if (buffer)
{ {
if (retval) { if (retval) {
lstrcpynAtoW( buffer, buffer2, buflen ); lstrcpynAtoW( buffer, buffer2, buflen );
retval = strlenW( buffer ); retval = lstrlenW( buffer );
} }
HeapFree( GetProcessHeap(), 0, buffer2 ); HeapFree( GetProcessHeap(), 0, buffer2 );
} }
return retval; return retval;
} }
@ -179,28 +217,27 @@ static INT load_messageW( HMODULE instance, UINT id, WORD lang,
* FIXME: missing wrap, * FIXME: missing wrap,
*/ */
DWORD WINAPI FormatMessageA( DWORD WINAPI FormatMessageA(
DWORD dwFlags, DWORD dwFlags,
LPCVOID lpSource, LPCVOID lpSource,
DWORD dwMessageId, DWORD dwMessageId,
DWORD dwLanguageId, DWORD dwLanguageId,
LPSTR lpBuffer, LPSTR lpBuffer,
DWORD nSize, DWORD nSize,
va_list* _args ) va_list* _args )
{ {
LPDWORD args=(LPDWORD)_args; LPDWORD args=(LPDWORD)_args;
#if defined(__i386__) || defined(__sparc__) #if defined(__i386__) || defined(__sparc__)
/* This implementation is completely dependent on the format of the va_list on x86 CPUs */ /* This implementation is completely dependant on the format of the va_list on x86 CPUs */
LPSTR target,t; LPSTR target,t;
DWORD talloced; DWORD talloced;
LPSTR from,f; LPSTR from,f;
DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK; DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
BOOL eos = FALSE; BOOL eos = FALSE;
INT bufsize; INT bufsize;
HMODULE hmodule = (HMODULE)lpSource; HMODULE hmodule = (HMODULE)lpSource;
CHAR ch; CHAR ch;
TRACE("(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n", //TRACE("(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n", dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args);
dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args);
if ((dwFlags & FORMAT_MESSAGE_FROM_STRING) if ((dwFlags & FORMAT_MESSAGE_FROM_STRING)
&&((dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) &&((dwFlags & FORMAT_MESSAGE_FROM_SYSTEM)
|| (dwFlags & FORMAT_MESSAGE_FROM_HMODULE))) return 0; || (dwFlags & FORMAT_MESSAGE_FROM_HMODULE))) return 0;
@ -210,7 +247,7 @@ DWORD WINAPI FormatMessageA(
from = NULL; from = NULL;
if (dwFlags & FORMAT_MESSAGE_FROM_STRING) if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
{ {
from = HeapAlloc( GetProcessHeap(), 0, strlen((LPSTR)lpSource)+1 ); from = RtlAllocateHeap(RtlGetProcessHeap(), 0, lstrlenA((LPSTR)lpSource)+1 );
strcpy( from, (LPSTR)lpSource ); strcpy( from, (LPSTR)lpSource );
} }
else { else {
@ -218,14 +255,36 @@ DWORD WINAPI FormatMessageA(
if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE)
{ {
if (!hmodule) bufsize=load_messageA(hmodule,dwMessageId,dwLanguageId,NULL,100);
hmodule = GetModuleHandleW(NULL); if ((!bufsize) && (!dwLanguageId)) {
bufsize=load_messageA(hmodule,dwMessageId,dwLanguageId,NULL,100); bufsize=load_messageA(hmodule,dwMessageId,
MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),NULL,100);
if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),NULL,100);
if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),NULL,100);
if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),NULL,100);
if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NULL,100);
}
} }
if ((dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) && (!bufsize)) if ((dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) && (!bufsize))
{ {
hmodule = GetModuleHandleA("kernel32"); hmodule = GetModuleHandleA("kernel32");
bufsize=load_messageA(hmodule,dwMessageId,dwLanguageId,NULL,100); bufsize=load_messageA(hmodule,dwMessageId,dwLanguageId,NULL,100);
if ((!bufsize) && (!dwLanguageId)) {
bufsize=load_messageA(hmodule,dwMessageId,
MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),NULL,100);
if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),NULL,100);
if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),NULL,100);
if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),NULL,100);
if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NULL,100);
}
} }
if (!bufsize) { if (!bufsize) {
@ -233,17 +292,17 @@ DWORD WINAPI FormatMessageA(
return 0; return 0;
} }
from = HeapAlloc( GetProcessHeap(), 0, bufsize + 1 ); from = RtlAllocateHeap(RtlGetProcessHeap(), 0, bufsize + 1 );
load_messageA(hmodule,dwMessageId,dwLanguageId,from,bufsize+1); load_messageA(hmodule,dwMessageId,dwLanguageId,from,bufsize+1);
} }
target = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100); target = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, 100);
t = target; t = target;
talloced= 100; talloced= 100;
#define ADD_TO_T(c) do { \ #define ADD_TO_T(c) do { \
*t++=c;\ *t++=c;\
if (t-target == talloced) {\ if (t-target == talloced) {\
target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\ target = (char*)RtlReAllocateHeap(RtlGetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
t = target+talloced;\ t = target+talloced;\
talloced*=2;\ talloced*=2;\
}\ }\
@ -289,17 +348,17 @@ DWORD WINAPI FormatMessageA(
f++; f++;
if (NULL!=(x=strchr(f,'!'))) { if (NULL!=(x=strchr(f,'!'))) {
*x='\0'; *x='\0';
fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f)+2); fmtstr=RtlAllocateHeap(RtlGetProcessHeap(),0,lstrlenA(f)+2);
sprintf(fmtstr,"%%%s",f); sprintf(fmtstr,"%%%s",f);
f=x+1; f=x+1;
} else { } else {
fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f)+2); fmtstr=RtlAllocateHeap(RtlGetProcessHeap(),0,lstrlenA(f)+2);
sprintf(fmtstr,"%%%s",f); sprintf(fmtstr,"%%%s",f);
f+=strlen(f); /*at \0*/ f+=lstrlenA(f); /*at \0*/
} }
} else { } else {
if(!args) break; if(!args) break;
fmtstr = HeapAlloc(GetProcessHeap(),0,3); fmtstr = RtlAllocateHeap(RtlGetProcessHeap(),0,3);
strcpy( fmtstr, "%s" ); strcpy( fmtstr, "%s" );
} }
if (args) { if (args) {
@ -314,17 +373,17 @@ DWORD WINAPI FormatMessageA(
/* FIXME: precision and width components are not handled correctly */ /* FIXME: precision and width components are not handled correctly */
if ( (strcmp(fmtstr, "%ls") == 0) || (strcmp(fmtstr,"%S") == 0) ) { if ( (strcmp(fmtstr, "%ls") == 0) || (strcmp(fmtstr,"%S") == 0) ) {
sz = WideCharToMultiByte( CP_ACP, 0, *(WCHAR**)argliststart, -1, NULL, 0, NULL, NULL); sz = WideCharToMultiByte( CP_ACP, 0, *(WCHAR**)argliststart, -1, NULL, 0, NULL, NULL);
b = HeapAlloc(GetProcessHeap(), 0, sz); b = RtlAllocateHeap(RtlGetProcessHeap(), 0, sz);
WideCharToMultiByte( CP_ACP, 0, *(WCHAR**)argliststart, -1, b, sz, NULL, NULL); WideCharToMultiByte( CP_ACP, 0, *(WCHAR**)argliststart, -1, b, sz, NULL, NULL);
} else { } else {
b = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz = 1000); b = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sz = 1000);
/* CMF - This makes a BIG assumption about va_list */ /* CMF - This makes a BIG assumption about va_list */
TRACE("A BIG assumption\n"); TRACE("A BIG assumption\n");
_vsnprintf(b, sz, fmtstr, (va_list) argliststart); //vsnprintf(b, sz, fmtstr, (va_list) argliststart);
} }
for (x=b; *x; x++) ADD_TO_T(*x); for (x=b; *x; x++) ADD_TO_T(*x);
HeapFree(GetProcessHeap(),0,b); RtlFreeHeap(RtlGetProcessHeap(),0,b);
} else { } else {
/* NULL args - copy formatstr /* NULL args - copy formatstr
* (probably wrong) * (probably wrong)
@ -333,7 +392,7 @@ DWORD WINAPI FormatMessageA(
ADD_TO_T(*lastf++); ADD_TO_T(*lastf++);
} }
} }
HeapFree(GetProcessHeap(),0,fmtstr); RtlFreeHeap(GetProcessHeap(),0,fmtstr);
break; break;
case 'n': case 'n':
ADD_TO_T('\r'); ADD_TO_T('\r');
@ -380,9 +439,9 @@ DWORD WINAPI FormatMessageA(
} }
*t='\0'; *t='\0';
} }
talloced = strlen(target)+1; talloced = lstrlenA(target)+1;
if (nSize && talloced<nSize) { if (nSize && talloced<nSize) {
target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize); target = (char*)RtlReAllocateHeap(RtlGetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
} }
//TRACE("-- %s\n",debugstr_a(target)); //TRACE("-- %s\n",debugstr_a(target));
if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) { if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
@ -391,12 +450,12 @@ DWORD WINAPI FormatMessageA(
} else { } else {
lstrcpynA(lpBuffer,target,nSize); lstrcpynA(lpBuffer,target,nSize);
} }
HeapFree(GetProcessHeap(),0,target); RtlFreeHeap(RtlGetProcessHeap(),0,target);
if (from) HeapFree(GetProcessHeap(),0,from); if (from) RtlFreeHeap(RtlGetProcessHeap(),0,from);
TRACE("-- returning %d\n", (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ? strlen(*(LPSTR*)lpBuffer):strlen(lpBuffer)); //TRACE("-- returning %d\n", (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ? lstrlenA(*(LPSTR*)lpBuffer):lstrlenA(lpBuffer));
return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ? return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
strlen(*(LPSTR*)lpBuffer): lstrlenA(*(LPSTR*)lpBuffer):
strlen(lpBuffer); lstrlenA(lpBuffer);
#else #else
return 0; return 0;
#endif /* __i386__ */ #endif /* __i386__ */
@ -408,17 +467,17 @@ DWORD WINAPI FormatMessageA(
* FormatMessageW (KERNEL32.@) * FormatMessageW (KERNEL32.@)
*/ */
DWORD WINAPI FormatMessageW( DWORD WINAPI FormatMessageW(
DWORD dwFlags, DWORD dwFlags,
LPCVOID lpSource, LPCVOID lpSource,
DWORD dwMessageId, DWORD dwMessageId,
DWORD dwLanguageId, DWORD dwLanguageId,
LPWSTR lpBuffer, LPWSTR lpBuffer,
DWORD nSize, DWORD nSize,
va_list* _args ) va_list* _args)
{ {
LPDWORD args=(LPDWORD)_args; LPDWORD args=(LPDWORD)_args;
#if defined(__i386__) || defined(__sparc__) #if defined(__i386__) || defined(__sparc__)
/* This implementation is completely dependent on the format of the va_list on x86 CPUs */ /* This implementation is completely dependant on the format of the va_list on x86 CPUs */
LPSTR target,t; LPSTR target,t;
DWORD talloced; DWORD talloced;
LPSTR from,f; LPSTR from,f;
@ -428,31 +487,53 @@ DWORD WINAPI FormatMessageW(
HMODULE hmodule = (HMODULE)lpSource; HMODULE hmodule = (HMODULE)lpSource;
CHAR ch; CHAR ch;
TRACE("(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n", //TRACE("(0x%lx,%p,%ld,0x%lx,%p,%ld,%p)\n", dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args);
dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args);
if ((dwFlags & FORMAT_MESSAGE_FROM_STRING) if ((dwFlags & FORMAT_MESSAGE_FROM_STRING)
&&((dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) &&((dwFlags & FORMAT_MESSAGE_FROM_SYSTEM)
|| (dwFlags & FORMAT_MESSAGE_FROM_HMODULE))) return 0; || (dwFlags & FORMAT_MESSAGE_FROM_HMODULE))) return 0;
if (width && width != FORMAT_MESSAGE_MAX_WIDTH_MASK) if (width && width != FORMAT_MESSAGE_MAX_WIDTH_MASK) {
FIXME("line wrapping not supported.\n"); FIXME("line wrapping not supported.\n");
}
from = NULL; from = NULL;
if (dwFlags & FORMAT_MESSAGE_FROM_STRING) { if (dwFlags & FORMAT_MESSAGE_FROM_STRING) {
from = HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)lpSource); from = (LPSTR)HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)lpSource);
} }
else { else {
bufsize = 0; bufsize = 0;
if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE)
{ {
if (!hmodule) bufsize=load_messageA(hmodule,dwMessageId,dwLanguageId,NULL,100);
hmodule = GetModuleHandleW(NULL); if ((!bufsize) && (!dwLanguageId)) {
bufsize=load_messageA(hmodule,dwMessageId,dwLanguageId,NULL,100); bufsize=load_messageA(hmodule,dwMessageId,
MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),NULL,100);
if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),NULL,100);
if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),NULL,100);
if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),NULL,100);
if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NULL,100);
}
} }
if ((dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) && (!bufsize)) if ((dwFlags & FORMAT_MESSAGE_FROM_SYSTEM) && (!bufsize))
{ {
hmodule = GetModuleHandleA("kernel32"); hmodule = GetModuleHandleA("kernel32");
bufsize=load_messageA(hmodule,dwMessageId,dwLanguageId,NULL,100); bufsize=load_messageA(hmodule,dwMessageId,dwLanguageId,NULL,100);
if ((!bufsize) && (!dwLanguageId)) {
bufsize=load_messageA(hmodule,dwMessageId,
MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL),NULL,100);
if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),NULL,100);
if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),NULL,100);
if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
MAKELANGID(LANG_NEUTRAL,SUBLANG_SYS_DEFAULT),NULL,100);
if (!bufsize) bufsize=load_messageA(hmodule,dwMessageId,
MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),NULL,100);
}
} }
if (!bufsize) { if (!bufsize) {
@ -460,17 +541,17 @@ DWORD WINAPI FormatMessageW(
return 0; return 0;
} }
from = HeapAlloc( GetProcessHeap(), 0, bufsize + 1 ); from = RtlAllocateHeap(RtlGetProcessHeap(), 0, bufsize + 1 );
load_messageA(hmodule,dwMessageId,dwLanguageId,from,bufsize+1); load_messageA(hmodule,dwMessageId,dwLanguageId,from,bufsize+1);
} }
target = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100 ); target = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, 100 );
t = target; t = target;
talloced= 100; talloced= 100;
#define ADD_TO_T(c) do {\ #define ADD_TO_T(c) do {\
*t++=c;\ *t++=c;\
if (t-target == talloced) {\ if (t-target == talloced) {\
target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\ target = (char*)RtlReAllocateHeap(RtlGetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2);\
t = target+talloced;\ t = target+talloced;\
talloced*=2;\ talloced*=2;\
} \ } \
@ -516,17 +597,17 @@ DWORD WINAPI FormatMessageW(
f++; f++;
if (NULL!=(x=strchr(f,'!'))) { if (NULL!=(x=strchr(f,'!'))) {
*x='\0'; *x='\0';
fmtstr=HeapAlloc( GetProcessHeap(), 0, strlen(f)+2); fmtstr=RtlAllocateHeap(RtlGetProcessHeap(), 0, lstrlenA(f)+2);
sprintf(fmtstr,"%%%s",f); sprintf(fmtstr,"%%%s",f);
f=x+1; f=x+1;
} else { } else {
fmtstr=HeapAlloc(GetProcessHeap(),0,strlen(f)+2); fmtstr=RtlAllocateHeap(RtlGetProcessHeap(),0,lstrlenA(f));
sprintf(fmtstr,"%%%s",f); sprintf(fmtstr,"%%%s",f);
f+=strlen(f); /*at \0*/ f+=lstrlenA(f); /*at \0*/
} }
} else { } else {
if(!args) break; if(!args) break;
fmtstr = HeapAlloc( GetProcessHeap(),0,3); fmtstr = RtlAllocateHeap(RtlGetProcessHeap(),0,3);
strcpy( fmtstr, "%s" ); strcpy( fmtstr, "%s" );
} }
if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY) if (dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY)
@ -534,20 +615,20 @@ DWORD WINAPI FormatMessageW(
else else
argliststart=(*(DWORD**)args)+insertnr-1; argliststart=(*(DWORD**)args)+insertnr-1;
if (fmtstr[strlen(fmtstr)-1]=='s' && argliststart[0]) { if (fmtstr[lstrlenA(fmtstr)-1]=='s' && argliststart[0]) {
DWORD xarr[3]; DWORD xarr[3];
xarr[0]=(DWORD)HEAP_strdupWtoA(GetProcessHeap(),0,(LPWSTR)(*(argliststart+0))); xarr[0]=(DWORD)HEAP_strdupWtoA(RtlGetProcessHeap(),0,(LPWSTR)(*(argliststart+0)));
/* possible invalid pointers */ /* possible invalid pointers */
xarr[1]=*(argliststart+1); xarr[1]=*(argliststart+1);
xarr[2]=*(argliststart+2); xarr[2]=*(argliststart+2);
sprintfbuf=HeapAlloc(GetProcessHeap(),0,strlenW((LPWSTR)argliststart[0])*2+1); sprintfbuf=RtlAllocateHeap(RtlGetProcessHeap(),0,lstrlenW((LPWSTR)argliststart[0])*2+1);
/* CMF - This makes a BIG assumption about va_list */ /* CMF - This makes a BIG assumption about va_list */
vsprintf(sprintfbuf, fmtstr, (va_list) xarr); vsprintf(sprintfbuf, fmtstr, (va_list) xarr);
HeapFree(GetProcessHeap(), 0, (LPVOID) xarr[0]); RtlFreeHeap(RtlGetProcessHeap(), 0, (LPVOID) xarr[0]);
} else { } else {
sprintfbuf=HeapAlloc(GetProcessHeap(),0,100); sprintfbuf=RtlAllocateHeap(RtlGetProcessHeap(),0,100);
/* CMF - This makes a BIG assumption about va_list */ /* CMF - This makes a BIG assumption about va_list */
vsprintf(sprintfbuf, fmtstr, (va_list) argliststart); vsprintf(sprintfbuf, fmtstr, (va_list) argliststart);
@ -556,8 +637,8 @@ DWORD WINAPI FormatMessageW(
while (*x) { while (*x) {
ADD_TO_T(*x++); ADD_TO_T(*x++);
} }
HeapFree(GetProcessHeap(),0,sprintfbuf); RtlFreeHeap(RtlGetProcessHeap(),0,sprintfbuf);
HeapFree(GetProcessHeap(),0,fmtstr); RtlFreeHeap(RtlGetProcessHeap(),0,fmtstr);
break; break;
case 'n': case 'n':
ADD_TO_T('\r'); ADD_TO_T('\r');
@ -604,9 +685,9 @@ DWORD WINAPI FormatMessageW(
} }
*t='\0'; *t='\0';
} }
talloced = strlen(target)+1; talloced = lstrlenA(target)+1;
if (nSize && talloced<nSize) if (nSize && talloced<nSize)
target = (char*)HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize); target = (char*)RtlReAllocateHeap(RtlGetProcessHeap(),HEAP_ZERO_MEMORY,target,nSize);
if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) { if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
/* nSize is the MINIMUM size */ /* nSize is the MINIMUM size */
DWORD len = MultiByteToWideChar( CP_ACP, 0, target, -1, NULL, 0 ); DWORD len = MultiByteToWideChar( CP_ACP, 0, target, -1, NULL, 0 );
@ -618,13 +699,101 @@ DWORD WINAPI FormatMessageW(
if (nSize > 0 && !MultiByteToWideChar( CP_ACP, 0, target, -1, lpBuffer, nSize )) if (nSize > 0 && !MultiByteToWideChar( CP_ACP, 0, target, -1, lpBuffer, nSize ))
lpBuffer[nSize-1] = 0; lpBuffer[nSize-1] = 0;
} }
HeapFree(GetProcessHeap(),0,target); RtlFreeHeap(RtlGetProcessHeap(),0,target);
if (from) HeapFree(GetProcessHeap(),0,from); if (from) RtlFreeHeap(RtlGetProcessHeap(),0,from);
return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ? return (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) ?
strlenW(*(LPWSTR*)lpBuffer): lstrlenW(*(LPWSTR*)lpBuffer):
strlenW(lpBuffer); lstrlenW(lpBuffer);
#else #else
return 0; return 0;
#endif /* __i386__ */ #endif /* __i386__ */
} }
#undef ADD_TO_T #undef ADD_TO_T
#else
/* EXPORTED */
/*
* @unimplemented
*/
DWORD
STDCALL
FormatMessageW(
DWORD dwFlags,
LPCVOID lpSource,
DWORD dwMessageId,
DWORD dwLanguageId,
LPWSTR lpBuffer,
DWORD nSize,
va_list* Arguments)
{
// RtlFormatMessage
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
/*
* @unimplemented
*/
DWORD
STDCALL
FormatMessageA(
DWORD dwFlags,
LPCVOID lpSource,
DWORD dwMessageId,
DWORD dwLanguageId,
LPSTR lpBuffer,
DWORD nSize,
va_list* Arguments)
{
HLOCAL pBuf = NULL;
//LPSTR pBuf = NULL;
#define MAX_MSG_STR_LEN 200
if (lpBuffer != NULL) {
if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER) {
pBuf = LocalAlloc(LPTR, max(nSize, MAX_MSG_STR_LEN));
if (pBuf == NULL) {
return 0;
}
*(LPSTR*)lpBuffer = pBuf;
} else {
pBuf = *(LPSTR*)lpBuffer;
}
if (dwFlags & FORMAT_MESSAGE_FROM_STRING) {
} else {
}
//FORMAT_MESSAGE_IGNORE_INSERTS
//FORMAT_MESSAGE_FROM_STRING
//FORMAT_MESSAGE_FROM_HMODULE
//FORMAT_MESSAGE_FROM_SYSTEM
//FORMAT_MESSAGE_ARGUMENT_ARRAY
}
/*
if (FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,
0,
error,
MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
(PTSTR)&msg,
0,
NULL)
)
*/
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return 0;
}
#endif
/* EOF */