[WIN32SS][LPK] Add BiDi support to menus and window captions (#738)

Added callback function that redirects calls to GreExtTextOutW that didn't went through lpk BiDi processing, calls that are from the kernel.

Completely solves JIRA issue CORE-6910.
This commit is contained in:
Baruch Rutman 2018-08-23 20:43:12 +03:00 committed by Hermès BÉLUSCA - MAÏTO
parent b277cbdf22
commit e7d2bbe726
5 changed files with 164 additions and 13 deletions

View File

@ -78,10 +78,9 @@ LpkExtTextOut(
if ((GetLayout(hdc) & LAYOUT_RTL) || (GetTextAlign(hdc) & TA_RTLREADING))
fuOptions |= ETO_RTLREADING;
/* If text direction is RTL change flag to account neutral characters
BUG: disables reordering of propsheet titles */
/* if (fuOptions & ETO_RTLREADING)
dwSICFlags = SIC_NEUTRAL; */
/* If text direction is RTL change flag to account neutral characters */
if (fuOptions & ETO_RTLREADING)
dwSICFlags |= SIC_NEUTRAL;
/* Check if the string requires complex script processing and not a "glyph indices" array */
if (ScriptIsComplex(lpString, uCount, dwSICFlags) == S_OK && !(fuOptions & ETO_GLYPH_INDEX))

View File

@ -17,7 +17,8 @@
#define USER32_CALLBACK_DDEPOST (13)
#define USER32_CALLBACK_DDEGET (14)
#define USER32_CALLBACK_SETOBM (15)
#define USER32_CALLBACK_MAXIMUM (15)
#define USER32_CALLBACK_LPK (16)
#define USER32_CALLBACK_MAXIMUM (16)
typedef struct _WINDOWPROC_CALLBACK_ARGUMENTS
{
@ -139,6 +140,18 @@ typedef struct _SETOBM_CALLBACK_ARGUMENTS
struct tagOEMBITMAPINFO oembmi[93];
} SETOBM_CALLBACK_ARGUMENTS, *PSETOBM_CALLBACK_ARGUMENTS;
typedef struct _LPK_CALLBACK_ARGUMENTS
{
LPWSTR lpString;
HDC hdc;
INT x;
INT y;
UINT flags;
RECT rect;
UINT count;
BOOL bRect;
} LPK_CALLBACK_ARGUMENTS, *PLPK_CALLBACK_ARGUMENTS;
NTSTATUS WINAPI
User32CallCopyImageFromKernel(PVOID Arguments, ULONG ArgumentLength);
NTSTATUS WINAPI
@ -171,4 +184,6 @@ NTSTATUS WINAPI
User32CallDDEGetFromKernel(PVOID Arguments, ULONG ArgumentLength);
NTSTATUS WINAPI
User32CallOBMFromKernel(PVOID Arguments, ULONG ArgumentLength);
NTSTATUS WINAPI
User32CallLPKFromKernel(PVOID Arguments, ULONG ArgumentLength);
#endif /* __INCLUDE_USER32_CALLBACK_H */

View File

@ -9,6 +9,9 @@
#include <win32k.h>
DBG_DEFAULT_CHANNEL(UserPainting);
BOOL UserExtTextOutW(HDC hdc, INT x, INT y, UINT flags, PRECTL lprc,
LPCWSTR lpString, UINT count);
/* PRIVATE FUNCTIONS **********************************************************/
/**
@ -2145,15 +2148,13 @@ UserDrawCaptionText(
if (Ret)
{ // Faster while in setup.
GreExtTextOutW( hDc,
UserExtTextOutW( hDc,
lpRc->left,
lpRc->top + (lpRc->bottom - lpRc->top - Size.cy) / 2, // DT_SINGLELINE && DT_VCENTER
ETO_CLIPPED,
(RECTL *)lpRc,
Text->Buffer,
Length,
NULL,
0 );
Length);
}
else
{

View File

@ -939,6 +939,120 @@ static void TEXT_DrawUnderscore (HDC hdc, int x, int y, const WCHAR *str, int of
#endif
}
#ifdef _WIN32K_
/***********************************************************************
* UserExtTextOutW
*
* Callback to usermode to use ExtTextOut, which will apply complex
* script processing if needed and then draw it
*
* Parameters
* hdc [in] The handle of the DC for drawing
* x [in] The x location of the string
* y [in] The y location of the string
* flags [in] ExtTextOut flags
* lprc [in] Clipping rectangle (if not NULL)
* lpString [in] String to be drawn
* count [in] String length
*/
BOOL UserExtTextOutW(HDC hdc,
INT x,
INT y,
UINT flags,
PRECTL lprc,
LPCWSTR lpString,
UINT count)
{
PVOID ResultPointer;
ULONG ResultLength;
ULONG ArgumentLength;
ULONG_PTR pStringBuffer;
NTSTATUS Status;
PLPK_CALLBACK_ARGUMENTS Argument;
BOOL bResult;
ArgumentLength = sizeof(LPK_CALLBACK_ARGUMENTS);
pStringBuffer = ArgumentLength;
ArgumentLength += sizeof(WCHAR) * (count + 2);
Argument = IntCbAllocateMemory(ArgumentLength);
if (!Argument)
{
goto fallback;
}
/* Initialize struct members */
Argument->hdc = hdc;
Argument->x = x;
Argument->y = y;
Argument->flags = flags;
Argument->count = count;
if (lprc)
{
Argument->rect = *lprc;
Argument->bRect = TRUE;
}
else
{
RtlZeroMemory(&Argument->rect, sizeof(RECT));
Argument->bRect = FALSE;
}
/* Align lpString
mimicks code from co_IntClientLoadLibrary */
Argument->lpString = (LPWSTR)pStringBuffer;
pStringBuffer += (ULONG_PTR)Argument;
Status = RtlStringCchCopyNW((LPWSTR)pStringBuffer, count + 1, lpString, count);
if (!NT_SUCCESS(Status))
{
IntCbFreeMemory(Argument);
goto fallback;
}
UserLeaveCo();
Status = KeUserModeCallback(USER32_CALLBACK_LPK,
Argument,
ArgumentLength,
&ResultPointer,
&ResultLength);
UserEnterCo();
IntCbFreeMemory(Argument);
if (NT_SUCCESS(Status))
{
_SEH2_TRY
{
ProbeForRead(ResultPointer, sizeof(BOOL), 1);
bResult = *(LPBOOL)ResultPointer;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
ERR("Failed to copy result from user mode!\n");
Status = _SEH2_GetExceptionCode();
}
_SEH2_END;
}
if (!NT_SUCCESS(Status))
{
goto fallback;
}
return bResult;
fallback:
return GreExtTextOutW(hdc, x, y, flags, lprc, lpString, count, NULL, 0);
}
#endif
/***********************************************************************
* DrawTextExW (USER32.@)
*
@ -1201,10 +1315,10 @@ INT WINAPI DrawTextExWorker( HDC hdc,
else
len_seg = len;
#ifdef _WIN32K_
if (!GreExtTextOutW( hdc, xseg, y,
((flags & DT_NOCLIP) ? 0 : ETO_CLIPPED) |
((flags & DT_RTLREADING) ? ETO_RTLREADING : 0),
rect, str, len_seg, NULL, 0 ))
if (!UserExtTextOutW( hdc, xseg, y,
((flags & DT_NOCLIP) ? 0 : ETO_CLIPPED) |
((flags & DT_RTLREADING) ? ETO_RTLREADING : 0),
rect, str, len_seg))
#else
if (!ExtTextOutW( hdc, xseg, y,
((flags & DT_NOCLIP) ? 0 : ETO_CLIPPED) |

View File

@ -205,6 +205,7 @@ PVOID apfnDispatch[USER32_CALLBACK_MAXIMUM + 1] =
User32CallDDEPostFromKernel,
User32CallDDEGetFromKernel,
User32CallOBMFromKernel,
User32CallLPKFromKernel,
};
@ -641,3 +642,24 @@ User32CallOBMFromKernel(PVOID Arguments, ULONG ArgumentLength)
return ZwCallbackReturn(Arguments, ArgumentLength, STATUS_SUCCESS);
}
NTSTATUS WINAPI User32CallLPKFromKernel(PVOID Arguments, ULONG ArgumentLength)
{
BOOL bResult;
PLPK_CALLBACK_ARGUMENTS Argument;
Argument = (PLPK_CALLBACK_ARGUMENTS)Arguments;
Argument->lpString = (LPWSTR)((ULONG_PTR)Argument->lpString + (ULONG_PTR)Argument);
bResult = ExtTextOutW(Argument->hdc,
Argument->x,
Argument->y,
Argument->flags,
(Argument->bRect) ? &Argument->rect : NULL,
Argument->lpString,
Argument->count,
NULL);
return ZwCallbackReturn(&bResult, sizeof(BOOL), STATUS_SUCCESS);
}