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/inc... ============================================================================== --- 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/ntu... ============================================================================== --- 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/ntu... ============================================================================== --- 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/obj... ============================================================================== --- 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