[kernel32]

sync format_msg.c with wine 1.7.11

svn path=/trunk/; revision=62234
This commit is contained in:
Christoph von Wittich 2014-02-17 21:51:48 +00:00
parent d76955a546
commit 9a2dc33fb5

View file

@ -115,7 +115,7 @@ static LPCWSTR format_insert( BOOL unicode_caller, int insert, LPCWSTR format,
DWORD flags, struct format_args *args, DWORD flags, struct format_args *args,
LPWSTR *result ) LPWSTR *result )
{ {
static const WCHAR fmt_lu[] = {'%','l','u',0}; static const WCHAR fmt_u[] = {'%','u',0};
WCHAR *wstring = NULL, *p, fmt[256]; WCHAR *wstring = NULL, *p, fmt[256];
ULONG_PTR arg; ULONG_PTR arg;
int size; int size;
@ -155,7 +155,7 @@ static LPCWSTR format_insert( BOOL unicode_caller, int insert, LPCWSTR format,
{ {
if (*format == '*') if (*format == '*')
{ {
p += sprintfW( p, fmt_lu, get_arg( insert, flags, args )); p += sprintfW( p, fmt_u, get_arg( insert, flags, args ));
insert = -1; insert = -1;
format++; format++;
} }
@ -168,7 +168,7 @@ static LPCWSTR format_insert( BOOL unicode_caller, int insert, LPCWSTR format,
*p++ = *format++; *p++ = *format++;
if (*format == '*') if (*format == '*')
{ {
p += sprintfW( p, fmt_lu, get_arg( insert, flags, args )); p += sprintfW( p, fmt_u, get_arg( insert, flags, args ));
insert = -1; insert = -1;
format++; format++;
} }
@ -198,7 +198,7 @@ static LPCWSTR format_insert( BOOL unicode_caller, int insert, LPCWSTR format,
(unicode_caller && format[0] == 'C') || (unicode_caller && format[0] == 'C') ||
(!unicode_caller && format[0] == 'c')) (!unicode_caller && format[0] == 'c'))
{ {
char ch = (char)arg; char ch = arg;
wstring = HeapAlloc( GetProcessHeap(), 0, 2 * sizeof(WCHAR) ); wstring = HeapAlloc( GetProcessHeap(), 0, 2 * sizeof(WCHAR) );
MultiByteToWideChar( CP_ACP, 0, &ch, 1, wstring, 1 ); MultiByteToWideChar( CP_ACP, 0, &ch, 1, wstring, 1 );
wstring[1] = 0; wstring[1] = 0;
@ -249,31 +249,85 @@ static LPCWSTR format_insert( BOOL unicode_caller, int insert, LPCWSTR format,
return format; return format;
} }
struct _format_message_data
{
LPWSTR formatted;
DWORD size;
LPWSTR t;
LPWSTR space;
BOOL inspace;
DWORD width, w;
};
static void format_add_char(struct _format_message_data *fmd, WCHAR c)
{
*fmd->t++ = c;
if (fmd->width && fmd->width != FORMAT_MESSAGE_MAX_WIDTH_MASK)
{
switch (c) {
case '\r':
case '\n':
fmd->space = NULL;
fmd->inspace = FALSE;
fmd->w = 0;
break;
case ' ':
if (!fmd->inspace)
fmd->space = fmd->t - 1;
fmd->inspace = TRUE;
fmd->w++;
break;
default:
fmd->inspace = FALSE;
fmd->w++;
}
if (fmd->w == fmd->width) {
LPWSTR notspace;
if (fmd->space) {
notspace = fmd->space;
while (*notspace == ' ' && notspace != fmd->t)
notspace++;
} else
notspace = fmd->space = fmd->t;
fmd->w = fmd->t - notspace;
memmove(fmd->space+2, notspace, fmd->w * sizeof(*fmd->t));
*fmd->space++ = '\r';
*fmd->space++ = '\n';
fmd->t = fmd->space + fmd->w;
fmd->space = NULL;
fmd->inspace = FALSE;
}
}
if ((DWORD)(fmd->t - fmd->formatted) == fmd->size) {
DWORD_PTR ispace = fmd->space - fmd->formatted;
/* Allocate two extra characters so we can insert a '\r\n' in
* the middle of a word.
*/
fmd->formatted = HeapReAlloc(GetProcessHeap(), 0, fmd->formatted, (fmd->size * 2 + 2) * sizeof(WCHAR));
fmd->t = fmd->formatted + fmd->size;
if (fmd->space)
fmd->space = fmd->formatted + ispace;
fmd->size *= 2;
}
}
/********************************************************************** /**********************************************************************
* format_message (internal) * format_message (internal)
*/ */
static LPWSTR format_message( BOOL unicode_caller, DWORD dwFlags, LPCWSTR fmtstr, static LPWSTR format_message( BOOL unicode_caller, DWORD dwFlags, LPCWSTR fmtstr,
struct format_args *format_args ) struct format_args *format_args )
{ {
LPWSTR target,t; struct _format_message_data fmd;
DWORD talloced;
LPCWSTR f; LPCWSTR f;
DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
BOOL eos = FALSE; BOOL eos = FALSE;
WCHAR ch;
target = t = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, 100 * sizeof(WCHAR) ); fmd.size = 100;
talloced = 100; fmd.formatted = fmd.t = HeapAlloc( GetProcessHeap(), 0, (fmd.size + 2) * sizeof(WCHAR) );
#define ADD_TO_T(c) do {\
*t++=c;\
if ((DWORD)(t-target) == talloced) {\
target = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,target,talloced*2*sizeof(WCHAR));\
t = target+talloced;\
talloced*=2;\
} \
} while (0)
fmd.width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
fmd.w = 0;
fmd.inspace = FALSE;
fmd.space = NULL;
f = fmtstr; f = fmtstr;
while (*f && !eos) { while (*f && !eos) {
if (*f=='%') { if (*f=='%') {
@ -290,7 +344,7 @@ static LPWSTR format_message( BOOL unicode_caller, DWORD dwFlags, LPCWSTR fmtstr
(!(dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY) && !format_args->list)) (!(dwFlags & FORMAT_MESSAGE_ARGUMENT_ARRAY) && !format_args->list))
{ {
SetLastError(ERROR_INVALID_PARAMETER); SetLastError(ERROR_INVALID_PARAMETER);
HeapFree(GetProcessHeap(), 0, target); HeapFree(GetProcessHeap(), 0, fmd.formatted);
return NULL; return NULL;
} }
insertnr = *f-'0'; insertnr = *f-'0';
@ -307,20 +361,20 @@ static LPWSTR format_message( BOOL unicode_caller, DWORD dwFlags, LPCWSTR fmtstr
break; break;
} }
f = format_insert( unicode_caller, insertnr, f, dwFlags, format_args, &str ); f = format_insert( unicode_caller, insertnr, f, dwFlags, format_args, &str );
for (x = str; *x; x++) ADD_TO_T(*x); for (x = str; *x; x++) format_add_char(&fmd, *x);
HeapFree( GetProcessHeap(), 0, str ); HeapFree( GetProcessHeap(), 0, str );
break; break;
case 'n': case 'n':
ADD_TO_T('\r'); format_add_char(&fmd, '\r');
ADD_TO_T('\n'); format_add_char(&fmd, '\n');
f++; f++;
break; break;
case 'r': case 'r':
ADD_TO_T('\r'); format_add_char(&fmd, '\r');
f++; f++;
break; break;
case 't': case 't':
ADD_TO_T('\t'); format_add_char(&fmd, '\t');
f++; f++;
break; break;
case '0': case '0':
@ -329,53 +383,51 @@ static LPWSTR format_message( BOOL unicode_caller, DWORD dwFlags, LPCWSTR fmtstr
break; break;
case '\0': case '\0':
SetLastError(ERROR_INVALID_PARAMETER); SetLastError(ERROR_INVALID_PARAMETER);
HeapFree(GetProcessHeap(), 0, target); HeapFree(GetProcessHeap(), 0, fmd.formatted);
return NULL; return NULL;
ignore_inserts: ignore_inserts:
default: default:
if (dwFlags & FORMAT_MESSAGE_IGNORE_INSERTS) if (dwFlags & FORMAT_MESSAGE_IGNORE_INSERTS)
ADD_TO_T('%'); format_add_char(&fmd, '%');
ADD_TO_T(*f++); format_add_char(&fmd, *f++);
break; break;
} }
} else { } else {
ch = *f; WCHAR ch = *f;
f++; f++;
if (ch == '\r') { if (ch == '\r') {
if (*f == '\n') if (*f == '\n')
f++; f++;
if(width) if(fmd.width)
ADD_TO_T(' '); format_add_char(&fmd, ' ');
else else
{ {
ADD_TO_T('\r'); format_add_char(&fmd, '\r');
ADD_TO_T('\n'); format_add_char(&fmd, '\n');
} }
} else { } else {
if (ch == '\n') if (ch == '\n')
{ {
if(width) if(fmd.width)
ADD_TO_T(' '); format_add_char(&fmd, ' ');
else else
{ {
ADD_TO_T('\r'); format_add_char(&fmd, '\r');
ADD_TO_T('\n'); format_add_char(&fmd, '\n');
} }
} }
else else
ADD_TO_T(ch); format_add_char(&fmd, ch);
} }
} }
} }
*t = '\0'; *fmd.t = '\0';
return target; return fmd.formatted;
} }
#undef ADD_TO_T
/*********************************************************************** /***********************************************************************
* FormatMessageA (KERNEL32.@) * FormatMessageA (KERNEL32.@)
* FIXME: missing wrap,
*/ */
DWORD WINAPI FormatMessageA( DWORD WINAPI FormatMessageA(
DWORD dwFlags, DWORD dwFlags,
@ -391,7 +443,6 @@ DWORD WINAPI FormatMessageA(
LPWSTR target; LPWSTR target;
DWORD destlength; DWORD destlength;
LPWSTR from; LPWSTR from;
DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
TRACE("(0x%x,%p,%d,0x%x,%p,%d,%p)\n", TRACE("(0x%x,%p,%d,0x%x,%p,%d,%p)\n",
dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args); dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args);
@ -420,8 +471,6 @@ DWORD WINAPI FormatMessageA(
format_args.last = 0; format_args.last = 0;
} }
if (width && width != FORMAT_MESSAGE_MAX_WIDTH_MASK)
FIXME("line wrapping (%u) not supported.\n", width);
from = NULL; from = NULL;
if (dwFlags & FORMAT_MESSAGE_FROM_STRING) if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
{ {
@ -432,9 +481,9 @@ DWORD WINAPI FormatMessageA(
else if (dwFlags & (FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM)) else if (dwFlags & (FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM))
{ {
if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE)
from = load_message( (HMODULE)lpSource, dwMessageId, (WORD)dwLanguageId ); from = load_message( (HMODULE)lpSource, dwMessageId, dwLanguageId );
if (!from && (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM)) if (!from && (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM))
from = load_message( kernel32_handle, dwMessageId, (WORD)dwLanguageId ); from = load_message( kernel32_handle, dwMessageId, dwLanguageId );
if (!from) return 0; if (!from) return 0;
} }
else else
@ -497,7 +546,6 @@ DWORD WINAPI FormatMessageW(
LPWSTR target; LPWSTR target;
DWORD talloced; DWORD talloced;
LPWSTR from; LPWSTR from;
DWORD width = dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK;
TRACE("(0x%x,%p,%d,0x%x,%p,%d,%p)\n", TRACE("(0x%x,%p,%d,0x%x,%p,%d,%p)\n",
dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args); dwFlags,lpSource,dwMessageId,dwLanguageId,lpBuffer,nSize,args);
@ -524,8 +572,6 @@ DWORD WINAPI FormatMessageW(
format_args.last = 0; format_args.last = 0;
} }
if (width && width != FORMAT_MESSAGE_MAX_WIDTH_MASK)
FIXME("line wrapping not supported.\n");
from = NULL; from = NULL;
if (dwFlags & FORMAT_MESSAGE_FROM_STRING) { if (dwFlags & FORMAT_MESSAGE_FROM_STRING) {
from = HeapAlloc( GetProcessHeap(), 0, (strlenW(lpSource) + 1) * from = HeapAlloc( GetProcessHeap(), 0, (strlenW(lpSource) + 1) *
@ -535,9 +581,9 @@ DWORD WINAPI FormatMessageW(
else if (dwFlags & (FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM)) else if (dwFlags & (FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM))
{ {
if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE) if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE)
from = load_message( (HMODULE)lpSource, dwMessageId, (WORD)dwLanguageId ); from = load_message( (HMODULE)lpSource, dwMessageId, dwLanguageId );
if (!from && (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM)) if (!from && (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM))
from = load_message( kernel32_handle, dwMessageId, (WORD)dwLanguageId ); from = load_message( kernel32_handle, dwMessageId, dwLanguageId );
if (!from) return 0; if (!from) return 0;
} }
else else