[WIN32SS][LPK] Add BiDi support to menus and window captions (#738)
authorBaruch Rutman <peterooch@gmail.com>
Thu, 23 Aug 2018 17:43:12 +0000 (20:43 +0300)
committerHermès BÉLUSCA - MAÏTO <hermes.belusca-maito@reactos.org>
Thu, 23 Aug 2018 17:43:12 +0000 (19:43 +0200)
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
win32ss/include/callback.h
win32ss/user/ntuser/painting.c
win32ss/user/rtl/text.c
win32ss/user/user32/misc/dllmain.c

index a31d978..075778b 100644 (file)
@@ -78,10 +78,9 @@ LpkExtTextOut(
     if ((GetLayout(hdc) & LAYOUT_RTL) || (GetTextAlign(hdc) & TA_RTLREADING))
         fuOptions |= ETO_RTLREADING;
 
     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))
 
     /* 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))
index bc8caec..75eda68 100644 (file)
@@ -17,7 +17,8 @@
 #define USER32_CALLBACK_DDEPOST               (13)
 #define USER32_CALLBACK_DDEGET                (14)
 #define USER32_CALLBACK_SETOBM                (15)
 #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
 {
 
 typedef struct _WINDOWPROC_CALLBACK_ARGUMENTS
 {
@@ -139,6 +140,18 @@ typedef struct _SETOBM_CALLBACK_ARGUMENTS
     struct tagOEMBITMAPINFO oembmi[93];   
 } SETOBM_CALLBACK_ARGUMENTS, *PSETOBM_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
 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);
 User32CallDDEGetFromKernel(PVOID Arguments, ULONG ArgumentLength);
 NTSTATUS WINAPI
 User32CallOBMFromKernel(PVOID Arguments, ULONG ArgumentLength);
+NTSTATUS WINAPI
+User32CallLPKFromKernel(PVOID Arguments, ULONG ArgumentLength);
 #endif /* __INCLUDE_USER32_CALLBACK_H */
 #endif /* __INCLUDE_USER32_CALLBACK_H */
index 4ffcdab..c1f7cad 100644 (file)
@@ -9,6 +9,9 @@
 #include <win32k.h>
 DBG_DEFAULT_CHANNEL(UserPainting);
 
 #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 **********************************************************/
 
 /**
 /* PRIVATE FUNCTIONS **********************************************************/
 
 /**
@@ -2145,15 +2148,13 @@ UserDrawCaptionText(
 
    if (Ret)
    {  // Faster while in setup.
 
    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,
                       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
    {
    }
    else
    {
index d723c55..7670e2e 100644 (file)
@@ -939,6 +939,120 @@ static void TEXT_DrawUnderscore (HDC hdc, int x, int y, const WCHAR *str, int of
 #endif
 }
 
 #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.@)
  *
 /***********************************************************************
  *           DrawTextExW    (USER32.@)
  *
@@ -1201,10 +1315,10 @@ INT WINAPI DrawTextExWorker( HDC hdc,
                 else
                     len_seg = len;
 #ifdef _WIN32K_
                 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) |
 #else
                 if (!ExtTextOutW( hdc, xseg, y,
                                  ((flags & DT_NOCLIP) ? 0 : ETO_CLIPPED) |
index 704cb2c..e329b85 100644 (file)
@@ -205,6 +205,7 @@ PVOID apfnDispatch[USER32_CALLBACK_MAXIMUM + 1] =
     User32CallDDEPostFromKernel,
     User32CallDDEGetFromKernel,
     User32CallOBMFromKernel,
     User32CallDDEPostFromKernel,
     User32CallDDEGetFromKernel,
     User32CallOBMFromKernel,
+    User32CallLPKFromKernel,
 };
 
 
 };
 
 
@@ -641,3 +642,24 @@ User32CallOBMFromKernel(PVOID Arguments, ULONG ArgumentLength)
 
   return ZwCallbackReturn(Arguments, ArgumentLength, STATUS_SUCCESS);
 }
 
   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);
+}