https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e7d2bbe726f605d0a0c69…
commit e7d2bbe726f605d0a0c69f3e2add6ee84bba8124
Author: Baruch Rutman <peterooch(a)gmail.com>
AuthorDate: Thu Aug 23 20:43:12 2018 +0300
Commit: Hermès BÉLUSCA - MAÏTO <hermes.belusca-maito(a)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);
+}