https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e7d2bbe726f605d0a0c69f...
commit e7d2bbe726f605d0a0c69f3e2add6ee84bba8124 Author: Baruch Rutman peterooch@gmail.com AuthorDate: Thu Aug 23 20:43:12 2018 +0300 Commit: Hermès BÉLUSCA - MAÏTO hermes.belusca-maito@reactos.org CommitDate: Thu Aug 23 19:43:12 2018 +0200
[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. --- dll/win32/lpk/lpk.c | 7 +-- win32ss/include/callback.h | 17 +++++- win32ss/user/ntuser/painting.c | 9 +-- win32ss/user/rtl/text.c | 122 +++++++++++++++++++++++++++++++++++-- win32ss/user/user32/misc/dllmain.c | 22 +++++++ 5 files changed, 164 insertions(+), 13 deletions(-)
diff --git a/dll/win32/lpk/lpk.c b/dll/win32/lpk/lpk.c index a31d9787a0..075778ba7c 100644 --- a/dll/win32/lpk/lpk.c +++ b/dll/win32/lpk/lpk.c @@ -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)) diff --git a/win32ss/include/callback.h b/win32ss/include/callback.h index bc8caecb67..75eda686a2 100644 --- a/win32ss/include/callback.h +++ b/win32ss/include/callback.h @@ -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 */ diff --git a/win32ss/user/ntuser/painting.c b/win32ss/user/ntuser/painting.c index 4ffcdab989..c1f7cad77a 100644 --- a/win32ss/user/ntuser/painting.c +++ b/win32ss/user/ntuser/painting.c @@ -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 { diff --git a/win32ss/user/rtl/text.c b/win32ss/user/rtl/text.c index d723c55f57..7670e2e595 100644 --- a/win32ss/user/rtl/text.c +++ b/win32ss/user/rtl/text.c @@ -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) | diff --git a/win32ss/user/user32/misc/dllmain.c b/win32ss/user/user32/misc/dllmain.c index 704cb2c49a..e329b85229 100644 --- a/win32ss/user/user32/misc/dllmain.c +++ b/win32ss/user/user32/misc/dllmain.c @@ -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); +}