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