Author: tkreuzer
Date: Sun Dec 21 21:58:04 2008
New Revision: 38261
URL:
http://svn.reactos.org/svn/reactos?rev=38261&view=rev
Log:
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.
Modified:
trunk/reactos/subsystems/win32/win32k/include/text.h
trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c
trunk/reactos/subsystems/win32/win32k/ntuser/painting.c
trunk/reactos/subsystems/win32/win32k/objects/freetype.c
Modified: trunk/reactos/subsystems/win32/win32k/include/text.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/in…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/include/text.h [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/include/text.h [iso-8859-1] Sun Dec 21 21:58:04
2008
@@ -104,6 +104,8 @@
BOOL FASTCALL IntGdiGetFontResourceInfo(PUNICODE_STRING,PVOID,DWORD*,DWORD);
BOOL FASTCALL ftGdiRealizationInfo(PFONTGDI,PREALIZATION_INFO);
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) \
ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&W32Process->PrivateFontListLock)
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/nt…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c [iso-8859-1] Sun Dec 21
21:58:04 2008
@@ -1536,7 +1536,7 @@
align_old = IntGdiSetTextAlign(hDC, TA_RIGHT);
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);
IntGdiSetTextAlign(hDC, align_old);
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/painting.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/nt…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/painting.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/painting.c [iso-8859-1] Sun Dec 21
21:58:04 2008
@@ -1594,7 +1594,7 @@
//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,
Text->Length/sizeof(WCHAR), NULL, 0);
Modified: trunk/reactos/subsystems/win32/win32k/objects/freetype.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ob…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/objects/freetype.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/objects/freetype.c [iso-8859-1] Sun Dec 21
21:58:04 2008
@@ -3079,15 +3079,15 @@
BOOL
APIENTRY
-NtGdiExtTextOutW(
+GreExtTextOutW(
IN HDC hDC,
IN INT XStart,
IN INT YStart,
IN UINT fuOptions,
IN OPTIONAL LPRECT lprc,
- IN LPWSTR UnsafeString,
+ IN LPWSTR String,
IN INT Count,
- IN OPTIONAL LPINT UnsafeDx,
+ IN OPTIONAL LPINT Dx,
IN DWORD dwCodePage)
{
/*
@@ -3108,7 +3108,7 @@
LONGLONG TextLeft, RealXStart;
ULONG TextTop, previous, BackgroundLeft;
FT_Bool use_kerning;
- RECTL DestRect, MaskRect, SpecifiedDestRect;
+ RECTL DestRect, MaskRect;
POINTL SourcePoint, BrushOrigin;
HBRUSH hBrushFg = NULL;
PGDIBRUSHOBJ BrushFg = NULL;
@@ -3129,11 +3129,8 @@
ULONG Mode;
FT_Render_Mode RenderMode;
BOOLEAN Render;
- NTSTATUS Status;
- INT *Dx = NULL;
POINT Start;
BOOL DoBreak = FALSE;
- LPCWSTR String, SafeString = NULL;
HPALETTE hDestPalette;
// TODO: Write test-cases to exactly match real Windows in different
@@ -3155,48 +3152,10 @@
if (!Dc_Attr) Dc_Attr = &dc->Dc_Attr;
/* Check if String is valid */
- if ((Count > 0xFFFF) || (Count > 0 && UnsafeString == NULL))
+ if ((Count > 0xFFFF) || (Count > 0 && String == NULL))
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
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))
@@ -3205,8 +3164,8 @@
XStart,
YStart,
fuOptions,
- (const RECT *)&SpecifiedDestRect,
- SafeString,
+ (const RECT *)lprc,
+ String,
Count,
(const INT *)Dx)) goto fail;
goto good;
@@ -3214,7 +3173,7 @@
if (lprc && (fuOptions & (ETO_OPAQUE | ETO_CLIPPED)))
{
- IntLPtoDP(dc, (POINT *) &SpecifiedDestRect, 2);
+ IntLPtoDP(dc, (POINT *)lprc, 2);
}
BitmapObj = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
@@ -3288,10 +3247,10 @@
if ((fuOptions & ETO_OPAQUE) && lprc)
{
- DestRect.left = SpecifiedDestRect.left + dc->ptlDCOrig.x;
- DestRect.top = SpecifiedDestRect.top + dc->ptlDCOrig.y;
- DestRect.right = SpecifiedDestRect.right + dc->ptlDCOrig.x;
- DestRect.bottom = SpecifiedDestRect.bottom + dc->ptlDCOrig.y;
+ DestRect.left = lprc->left + dc->ptlDCOrig.x;
+ DestRect.top = lprc->top + dc->ptlDCOrig.y;
+ DestRect.right = lprc->right + dc->ptlDCOrig.x;
+ DestRect.bottom = lprc->bottom + dc->ptlDCOrig.y;
IntLPtoDP(dc, (LPPOINT)&DestRect, 2);
IntEngBitBlt(
&BitmapObj->SurfObj,
@@ -3602,12 +3561,12 @@
if (lprc &&
(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
// through this loop, since it's breaking after the drawing is done,
// and x is always incremented.
- DestRect.right = SpecifiedDestRect.right + dc->ptlDCOrig.x;
+ DestRect.right = lprc->right + dc->ptlDCOrig.x;
DoBreak = TRUE;
}
@@ -3661,14 +3620,6 @@
BRUSHOBJ_UnlockBrush(BrushFg);
NtGdiDeleteObject(hBrushFg);
good:
- if (NULL != SafeString)
- {
- ExFreePoolWithTag((void*)SafeString, TAG_GDITEXT);
- }
- if (NULL != Dx)
- {
- ExFreePoolWithTag(Dx, TAG_GDITEXT);
- }
DC_UnlockDc( dc );
return TRUE;
@@ -3692,18 +3643,131 @@
BRUSHOBJ_UnlockBrush(BrushFg);
NtGdiDeleteObject(hBrushFg);
}
- if (NULL != SafeString)
- {
- ExFreePoolWithTag((void*)SafeString, TAG_GDITEXT);
- }
- if (NULL != Dx)
- {
- ExFreePoolWithTag(Dx, TAG_GDITEXT);
- }
DC_UnlockDc(dc);
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