Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 12 commits into from Aug 23, 2018
7 changes: 3 additions & 4 deletions dll/win32/lpk/lpk.c
Expand Up @@ -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))
Expand Down
17 changes: 16 additions & 1 deletion win32ss/include/callback.h
Expand Up @@ -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
{
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 */
9 changes: 5 additions & 4 deletions win32ss/user/ntuser/painting.c
Expand Up @@ -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 **********************************************************/

/**
Expand Down Expand Up @@ -2145,15 +2148,13 @@ UserDrawCaptionText(

if (Ret)
{ // Faster while in setup.
GreExtTextOutW( hDc,
UserExtTextOutW( hDc,
lpRc->left,
lpRc->top + (lpRc->bottom - lpRc->top) / 2 - Size.cy / 2, // DT_SINGLELINE && DT_VCENTER
ETO_CLIPPED,
(RECTL *)lpRc,
Text->Buffer,
Length,
NULL,
0 );
Length);
}
else
{
Expand Down
100 changes: 96 additions & 4 deletions win32ss/user/rtl/text.c
Expand Up @@ -939,6 +939,98 @@ static void TEXT_DrawUnderscore (HDC hdc, int x, int y, const WCHAR *str, int of
#endif
}

#ifdef _WIN32K_
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 = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not need to be zero-initialized.

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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're leaving rect uninitialized here, which leaks kernel memory contents to user mode.

}

/* Align lpString
mimicks code from co_IntClientLoadLibrary */
Argument->lpString = (LPWSTR)pStringBuffer;
pStringBuffer += (ULONG_PTR)Argument;
RtlStringCchCopyNW((LPWSTR)pStringBuffer, count + 1, lpString, count);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should probably check the return from this.


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.@)
*
Expand Down Expand Up @@ -1198,10 +1290,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) |
Expand Down
22 changes: 22 additions & 0 deletions win32ss/user/user32/misc/dllmain.c
Expand Up @@ -205,6 +205,7 @@ PVOID apfnDispatch[USER32_CALLBACK_MAXIMUM + 1] =
User32CallDDEPostFromKernel,
User32CallDDEGetFromKernel,
User32CallOBMFromKernel,
User32CallLPKFromKernel,
};


Expand Down Expand Up @@ -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,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the future this certainly will have to be generalized.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean by "generalization"?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Err forget what I've just said. I indeed see in the user32 symbols that there is indeed a special callback for ExtTextOutW (ClientExtTextOutW).
https://www.reactos.org/wiki/Techwiki:Win32k/apfnDispatch

Argument->x,
Argument->y,
Argument->flags,
(Argument->bRect) ? &Argument->rect : NULL,
Argument->lpString,
Argument->count,
NULL);

return ZwCallbackReturn(&bResult, sizeof(BOOL), STATUS_SUCCESS);
}