mirror of
https://github.com/reactos/reactos.git
synced 2025-04-27 09:00:27 +00:00
Some people were thinking they could use NtGdiExtTextOut from within Win32k and get away with it. Since MmCopyFromCaller is broken, it was actually working. Implement NtGdiExtTextOutW as a wrapper around the real function, that is now called GreExtTextOutW, using the naming style that ms also uses to get some more stucture in here. Also get rid of 2 pool allocations and use only one if a local buffer is not sufficient. Should get us more TextOut performance.
svn path=/trunk/; revision=38261
This commit is contained in:
parent
955a660368
commit
766c25b7e3
4 changed files with 139 additions and 73 deletions
|
@ -104,6 +104,8 @@ DWORD FASTCALL ftGdiGetFontData(PFONTGDI,DWORD,DWORD,PVOID,DWORD);
|
||||||
BOOL FASTCALL IntGdiGetFontResourceInfo(PUNICODE_STRING,PVOID,DWORD*,DWORD);
|
BOOL FASTCALL IntGdiGetFontResourceInfo(PUNICODE_STRING,PVOID,DWORD*,DWORD);
|
||||||
BOOL FASTCALL ftGdiRealizationInfo(PFONTGDI,PREALIZATION_INFO);
|
BOOL FASTCALL ftGdiRealizationInfo(PFONTGDI,PREALIZATION_INFO);
|
||||||
DWORD FASTCALL ftGdiGetKerningPairs(PFONTGDI,DWORD,LPKERNINGPAIR);
|
DWORD FASTCALL ftGdiGetKerningPairs(PFONTGDI,DWORD,LPKERNINGPAIR);
|
||||||
|
BOOL NTAPI GreExtTextOutW(IN HDC,IN INT,IN INT,IN UINT,IN OPTIONAL LPRECT,
|
||||||
|
IN LPWSTR, IN INT, IN OPTIONAL LPINT, IN DWORD);
|
||||||
|
|
||||||
#define IntLockProcessPrivateFonts(W32Process) \
|
#define IntLockProcessPrivateFonts(W32Process) \
|
||||||
ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&W32Process->PrivateFontListLock)
|
ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&W32Process->PrivateFontListLock)
|
||||||
|
|
|
@ -1536,7 +1536,7 @@ NtUserPaintDesktop(HDC hDC)
|
||||||
align_old = IntGdiSetTextAlign(hDC, TA_RIGHT);
|
align_old = IntGdiSetTextAlign(hDC, TA_RIGHT);
|
||||||
mode_old = IntGdiSetBkMode(hDC, TRANSPARENT);
|
mode_old = IntGdiSetBkMode(hDC, TRANSPARENT);
|
||||||
|
|
||||||
NtGdiExtTextOutW(hDC, rect.right-16, rect.bottom-48, 0, NULL, s_wszVersion, len, NULL, 0);
|
GreExtTextOutW(hDC, rect.right-16, rect.bottom-48, 0, NULL, s_wszVersion, len, NULL, 0);
|
||||||
|
|
||||||
IntGdiSetBkMode(hDC, mode_old);
|
IntGdiSetBkMode(hDC, mode_old);
|
||||||
IntGdiSetTextAlign(hDC, align_old);
|
IntGdiSetTextAlign(hDC, align_old);
|
||||||
|
|
|
@ -1594,7 +1594,7 @@ UserDrawCaptionText(HDC hDc,
|
||||||
|
|
||||||
//FIXME: If string doesn't fit to rc, truncate it and add ellipsis.
|
//FIXME: If string doesn't fit to rc, truncate it and add ellipsis.
|
||||||
|
|
||||||
NtGdiExtTextOutW(hDc, lpRc->left,
|
GreExtTextOutW(hDc, lpRc->left,
|
||||||
lpRc->top, 0, NULL, Text->Buffer,
|
lpRc->top, 0, NULL, Text->Buffer,
|
||||||
Text->Length/sizeof(WCHAR), NULL, 0);
|
Text->Length/sizeof(WCHAR), NULL, 0);
|
||||||
|
|
||||||
|
|
|
@ -3079,15 +3079,15 @@ NtGdiGetFontFamilyInfo(HDC Dc,
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
APIENTRY
|
APIENTRY
|
||||||
NtGdiExtTextOutW(
|
GreExtTextOutW(
|
||||||
IN HDC hDC,
|
IN HDC hDC,
|
||||||
IN INT XStart,
|
IN INT XStart,
|
||||||
IN INT YStart,
|
IN INT YStart,
|
||||||
IN UINT fuOptions,
|
IN UINT fuOptions,
|
||||||
IN OPTIONAL LPRECT lprc,
|
IN OPTIONAL LPRECT lprc,
|
||||||
IN LPWSTR UnsafeString,
|
IN LPWSTR String,
|
||||||
IN INT Count,
|
IN INT Count,
|
||||||
IN OPTIONAL LPINT UnsafeDx,
|
IN OPTIONAL LPINT Dx,
|
||||||
IN DWORD dwCodePage)
|
IN DWORD dwCodePage)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -3108,7 +3108,7 @@ NtGdiExtTextOutW(
|
||||||
LONGLONG TextLeft, RealXStart;
|
LONGLONG TextLeft, RealXStart;
|
||||||
ULONG TextTop, previous, BackgroundLeft;
|
ULONG TextTop, previous, BackgroundLeft;
|
||||||
FT_Bool use_kerning;
|
FT_Bool use_kerning;
|
||||||
RECTL DestRect, MaskRect, SpecifiedDestRect;
|
RECTL DestRect, MaskRect;
|
||||||
POINTL SourcePoint, BrushOrigin;
|
POINTL SourcePoint, BrushOrigin;
|
||||||
HBRUSH hBrushFg = NULL;
|
HBRUSH hBrushFg = NULL;
|
||||||
PGDIBRUSHOBJ BrushFg = NULL;
|
PGDIBRUSHOBJ BrushFg = NULL;
|
||||||
|
@ -3129,11 +3129,8 @@ NtGdiExtTextOutW(
|
||||||
ULONG Mode;
|
ULONG Mode;
|
||||||
FT_Render_Mode RenderMode;
|
FT_Render_Mode RenderMode;
|
||||||
BOOLEAN Render;
|
BOOLEAN Render;
|
||||||
NTSTATUS Status;
|
|
||||||
INT *Dx = NULL;
|
|
||||||
POINT Start;
|
POINT Start;
|
||||||
BOOL DoBreak = FALSE;
|
BOOL DoBreak = FALSE;
|
||||||
LPCWSTR String, SafeString = NULL;
|
|
||||||
HPALETTE hDestPalette;
|
HPALETTE hDestPalette;
|
||||||
|
|
||||||
// TODO: Write test-cases to exactly match real Windows in different
|
// TODO: Write test-cases to exactly match real Windows in different
|
||||||
|
@ -3155,49 +3152,11 @@ NtGdiExtTextOutW(
|
||||||
if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
|
if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
|
||||||
|
|
||||||
/* Check if String is valid */
|
/* Check if String is valid */
|
||||||
if ((Count > 0xFFFF) || (Count > 0 && UnsafeString == NULL))
|
if ((Count > 0xFFFF) || (Count > 0 && String == NULL))
|
||||||
{
|
{
|
||||||
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (Count > 0)
|
|
||||||
{
|
|
||||||
SafeString = ExAllocatePoolWithTag(PagedPool, Count * sizeof(WCHAR), TAG_GDITEXT);
|
|
||||||
if (!SafeString)
|
|
||||||
{
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
Status = MmCopyFromCaller(SafeString, UnsafeString, Count * sizeof(WCHAR));
|
|
||||||
if (! NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String = SafeString;
|
|
||||||
|
|
||||||
if (NULL != UnsafeDx && Count > 0)
|
|
||||||
{
|
|
||||||
Dx = ExAllocatePoolWithTag(PagedPool, Count * sizeof(INT), TAG_GDITEXT);
|
|
||||||
if (NULL == Dx)
|
|
||||||
{
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
Status = MmCopyFromCaller(Dx, UnsafeDx, Count * sizeof(INT));
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lprc)
|
|
||||||
{
|
|
||||||
Status = MmCopyFromCaller(&SpecifiedDestRect, lprc, sizeof(RECT));
|
|
||||||
if (!NT_SUCCESS(Status))
|
|
||||||
{
|
|
||||||
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PATH_IsPathOpen(dc->DcLevel))
|
if (PATH_IsPathOpen(dc->DcLevel))
|
||||||
{
|
{
|
||||||
|
@ -3205,8 +3164,8 @@ NtGdiExtTextOutW(
|
||||||
XStart,
|
XStart,
|
||||||
YStart,
|
YStart,
|
||||||
fuOptions,
|
fuOptions,
|
||||||
(const RECT *)&SpecifiedDestRect,
|
(const RECT *)lprc,
|
||||||
SafeString,
|
String,
|
||||||
Count,
|
Count,
|
||||||
(const INT *)Dx)) goto fail;
|
(const INT *)Dx)) goto fail;
|
||||||
goto good;
|
goto good;
|
||||||
|
@ -3214,7 +3173,7 @@ NtGdiExtTextOutW(
|
||||||
|
|
||||||
if (lprc && (fuOptions & (ETO_OPAQUE | ETO_CLIPPED)))
|
if (lprc && (fuOptions & (ETO_OPAQUE | ETO_CLIPPED)))
|
||||||
{
|
{
|
||||||
IntLPtoDP(dc, (POINT *) &SpecifiedDestRect, 2);
|
IntLPtoDP(dc, (POINT *)lprc, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
|
BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
|
||||||
|
@ -3288,10 +3247,10 @@ NtGdiExtTextOutW(
|
||||||
|
|
||||||
if ((fuOptions & ETO_OPAQUE) && lprc)
|
if ((fuOptions & ETO_OPAQUE) && lprc)
|
||||||
{
|
{
|
||||||
DestRect.left = SpecifiedDestRect.left + dc->ptlDCOrig.x;
|
DestRect.left = lprc->left + dc->ptlDCOrig.x;
|
||||||
DestRect.top = SpecifiedDestRect.top + dc->ptlDCOrig.y;
|
DestRect.top = lprc->top + dc->ptlDCOrig.y;
|
||||||
DestRect.right = SpecifiedDestRect.right + dc->ptlDCOrig.x;
|
DestRect.right = lprc->right + dc->ptlDCOrig.x;
|
||||||
DestRect.bottom = SpecifiedDestRect.bottom + dc->ptlDCOrig.y;
|
DestRect.bottom = lprc->bottom + dc->ptlDCOrig.y;
|
||||||
IntLPtoDP(dc, (LPPOINT)&DestRect, 2);
|
IntLPtoDP(dc, (LPPOINT)&DestRect, 2);
|
||||||
IntEngBitBlt(
|
IntEngBitBlt(
|
||||||
&BitmapObj->SurfObj,
|
&BitmapObj->SurfObj,
|
||||||
|
@ -3602,12 +3561,12 @@ NtGdiExtTextOutW(
|
||||||
|
|
||||||
if (lprc &&
|
if (lprc &&
|
||||||
(fuOptions & ETO_CLIPPED) &&
|
(fuOptions & ETO_CLIPPED) &&
|
||||||
DestRect.right >= SpecifiedDestRect.right + dc->ptlDCOrig.x)
|
DestRect.right >= lprc->right + dc->ptlDCOrig.x)
|
||||||
{
|
{
|
||||||
// We do the check '>=' instead of '>' to possibly save an iteration
|
// We do the check '>=' instead of '>' to possibly save an iteration
|
||||||
// through this loop, since it's breaking after the drawing is done,
|
// through this loop, since it's breaking after the drawing is done,
|
||||||
// and x is always incremented.
|
// and x is always incremented.
|
||||||
DestRect.right = SpecifiedDestRect.right + dc->ptlDCOrig.x;
|
DestRect.right = lprc->right + dc->ptlDCOrig.x;
|
||||||
DoBreak = TRUE;
|
DoBreak = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3661,14 +3620,6 @@ NtGdiExtTextOutW(
|
||||||
BRUSHOBJ_UnlockBrush(BrushFg);
|
BRUSHOBJ_UnlockBrush(BrushFg);
|
||||||
NtGdiDeleteObject(hBrushFg);
|
NtGdiDeleteObject(hBrushFg);
|
||||||
good:
|
good:
|
||||||
if (NULL != SafeString)
|
|
||||||
{
|
|
||||||
ExFreePoolWithTag((void*)SafeString, TAG_GDITEXT);
|
|
||||||
}
|
|
||||||
if (NULL != Dx)
|
|
||||||
{
|
|
||||||
ExFreePoolWithTag(Dx, TAG_GDITEXT);
|
|
||||||
}
|
|
||||||
DC_UnlockDc( dc );
|
DC_UnlockDc( dc );
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@ -3692,19 +3643,132 @@ fail:
|
||||||
BRUSHOBJ_UnlockBrush(BrushFg);
|
BRUSHOBJ_UnlockBrush(BrushFg);
|
||||||
NtGdiDeleteObject(hBrushFg);
|
NtGdiDeleteObject(hBrushFg);
|
||||||
}
|
}
|
||||||
if (NULL != SafeString)
|
|
||||||
{
|
|
||||||
ExFreePoolWithTag((void*)SafeString, TAG_GDITEXT);
|
|
||||||
}
|
|
||||||
if (NULL != Dx)
|
|
||||||
{
|
|
||||||
ExFreePoolWithTag(Dx, TAG_GDITEXT);
|
|
||||||
}
|
|
||||||
DC_UnlockDc(dc);
|
DC_UnlockDc(dc);
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define STACK_TEXT_BUFFER_SIZE 50
|
||||||
|
BOOL
|
||||||
|
APIENTRY
|
||||||
|
NtGdiExtTextOutW(
|
||||||
|
IN HDC hDC,
|
||||||
|
IN INT XStart,
|
||||||
|
IN INT YStart,
|
||||||
|
IN UINT fuOptions,
|
||||||
|
IN OPTIONAL LPRECT UnsafeRect,
|
||||||
|
IN LPWSTR UnsafeString,
|
||||||
|
IN INT Count,
|
||||||
|
IN OPTIONAL LPINT UnsafeDx,
|
||||||
|
IN DWORD dwCodePage)
|
||||||
|
{
|
||||||
|
BOOL Result = FALSE;
|
||||||
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
RECT SafeRect;
|
||||||
|
BYTE LocalBuffer[STACK_TEXT_BUFFER_SIZE];
|
||||||
|
PVOID Buffer = LocalBuffer;
|
||||||
|
LPWSTR SafeString = NULL;
|
||||||
|
LPINT SafeDx = NULL;
|
||||||
|
ULONG BufSize, StringSize, DxSize = 0;
|
||||||
|
|
||||||
|
/* Check if String is valid */
|
||||||
|
if ((Count > 0xFFFF) || (Count > 0 && UnsafeString == NULL))
|
||||||
|
{
|
||||||
|
SetLastWin32Error(ERROR_INVALID_PARAMETER);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Count > 0)
|
||||||
|
{
|
||||||
|
/* Calculate buffer size for string and Dx values */
|
||||||
|
BufSize = StringSize = Count * sizeof(WCHAR);
|
||||||
|
if (UnsafeDx)
|
||||||
|
{
|
||||||
|
/* If ETO_PDY is specified, we have pairs of INTs */
|
||||||
|
DxSize = (Count * sizeof(INT)) * (fuOptions & ETO_PDY ? 2 : 1);
|
||||||
|
BufSize += DxSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if our local buffer is large enough */
|
||||||
|
if (BufSize > STACK_TEXT_BUFFER_SIZE)
|
||||||
|
{
|
||||||
|
/* It's not, allocate a temp buffer */
|
||||||
|
Buffer = ExAllocatePoolWithTag(PagedPool, BufSize, TAG_GDITEXT);
|
||||||
|
if (!Buffer)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Probe and copy user mode data to the buffer */
|
||||||
|
_SEH2_TRY
|
||||||
|
{
|
||||||
|
/* Probe and copy the string */
|
||||||
|
ProbeForRead(UnsafeString, StringSize, 1);
|
||||||
|
SafeString = Buffer;
|
||||||
|
memcpy((PVOID)SafeString, UnsafeString, StringSize);
|
||||||
|
|
||||||
|
/* If we have Dx values... */
|
||||||
|
if (UnsafeDx)
|
||||||
|
{
|
||||||
|
/* ... probe and copy them */
|
||||||
|
ProbeForRead(UnsafeDx, DxSize, 1);
|
||||||
|
SafeDx = (LPINT)(((ULONG_PTR)Buffer) + StringSize);
|
||||||
|
memcpy(SafeDx, UnsafeDx, DxSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
Status = _SEH2_GetExceptionCode();
|
||||||
|
}
|
||||||
|
_SEH2_END
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If we have a rect, copy it */
|
||||||
|
if (UnsafeRect)
|
||||||
|
{
|
||||||
|
_SEH2_TRY
|
||||||
|
{
|
||||||
|
ProbeForRead(UnsafeRect, sizeof(RECT), 1);
|
||||||
|
SafeRect = *UnsafeRect;
|
||||||
|
}
|
||||||
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
Status = _SEH2_GetExceptionCode();
|
||||||
|
}
|
||||||
|
_SEH2_END
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finally call the internal routine */
|
||||||
|
Result = GreExtTextOutW(hDC,
|
||||||
|
XStart,
|
||||||
|
YStart,
|
||||||
|
fuOptions,
|
||||||
|
&SafeRect,
|
||||||
|
SafeString,
|
||||||
|
Count,
|
||||||
|
SafeDx,
|
||||||
|
dwCodePage);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
/* If we allocated a buffer, free it */
|
||||||
|
if (Buffer != LocalBuffer)
|
||||||
|
{
|
||||||
|
ExFreePoolWithTag(Buffer, TAG_GDITEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result;;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @implemented
|
* @implemented
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in a new issue