diff --git a/dlls/user/text.c b/dlls/user/text.c index e72ed547f50..bfc9c628f32 100644 --- a/dlls/user/text.c +++ b/dlls/user/text.c @@ -334,6 +334,13 @@ static void TEXT_DrawUnderscore (HDC hdc, int x, int y, const WCHAR *str, int of /*********************************************************************** * DrawTextExW (USER32.@) + * + * The documentation on the extra space required for DT_MODIFYSTRING at MSDN + * is not quite complete, especially with regard to \0. We will assume that + * the returned string could have a length of up to i_count+3 and also have + * a trailing \0 (which would be 4 more than a not-null-terminated string but + * 3 more than a null-terminated string). If this is not so then increase + * the allowance in DrawTextExA. */ #define MAX_STATIC_BUFFER 1024 INT WINAPI DrawTextExW( HDC hdc, LPWSTR str, INT i_count, @@ -539,24 +546,51 @@ INT WINAPI DrawTextExW( HDC hdc, LPWSTR str, INT i_count, /*********************************************************************** * DrawTextExA (USER32.@) + * + * If DT_MODIFYSTRING is specified then there must be room for up to + * 4 extra characters. We take great care about just how much modified + * string we return. */ INT WINAPI DrawTextExA( HDC hdc, LPSTR str, INT count, LPRECT rect, UINT flags, LPDRAWTEXTPARAMS dtp ) { WCHAR *wstr; + WCHAR *p; INT ret = 0; + int i; DWORD wcount; + DWORD wmax; + DWORD amax; if (count == -1) count = strlen(str); if (!count) return 0; wcount = MultiByteToWideChar( CP_ACP, 0, str, count, NULL, 0 ); - wstr = HeapAlloc(GetProcessHeap(), 0, wcount * sizeof(WCHAR)); + wmax = wcount; + amax = count; + if (flags & DT_MODIFYSTRING) + { + wmax += 4; + amax += 4; + } + wstr = HeapAlloc(GetProcessHeap(), 0, wmax * sizeof(WCHAR)); if (wstr) { MultiByteToWideChar( CP_ACP, 0, str, count, wstr, wcount ); + if (flags & DT_MODIFYSTRING) + for (i=4, p=wstr+wcount; i--; p++) *p=0xFFFE; + /* Initialise the extra characters so that we can see which ones + * change. U+FFFE is guaranteed to be not a unicode character and + * so will not be generated by DrawTextEx itself. + */ ret = DrawTextExW( hdc, wstr, wcount, rect, flags, NULL ); if (flags & DT_MODIFYSTRING) - WideCharToMultiByte( CP_ACP, 0, wstr, -1, str, count, NULL, NULL ); + { + /* Unfortunately the returned string may contain multiple \0s + * and so we need to measure it ourselves. + */ + for (i=4, p=wstr+wcount; i-- && *p != 0xFFFE; p++) wcount++; + WideCharToMultiByte( CP_ACP, 0, wstr, wcount, str, amax, NULL, NULL ); + } HeapFree(GetProcessHeap(), 0, wstr); } return ret;