https://git.reactos.org/?p=reactos.git;a=commitdiff;h=6a3b1879a184e07dd52cb…
commit 6a3b1879a184e07dd52cbb7ac8edb78ca9e8ba23
Author: Baruch Rutman <peterooch(a)gmail.com>
AuthorDate: Wed Oct 24 22:34:38 2018 +0300
Commit: Hermès BÉLUSCA - MAÏTO <hermes.belusca-maito(a)reactos.org>
CommitDate: Wed Oct 24 21:34:38 2018 +0200
[LPK][GDI32] Enable mirroring via version resource (#965)
Add a mechanism that detects via the version resource whether it's needed to
mirror
the application layout or not. This is a "follow up" to commit 5b14b6f.
This code is taken from the GetProcessDefaultLayout() function from Wine
(called there "WIN_CreateWindowEx").
In Windows the version-resource mirroring happens when the GDI is loading the LPK.
- Implement mirroring via version resource. GDI linking on startup is required.
- GDI32: Add LPK loading on GDI startup.
To enable mirroring via version resource the lpk.dll must be loaded before any windows
are created.
This is done through GdiInitializeLanguagePack() function which is called in
GdiProcessSetup().
- LPK: Use Wine debug messaging.
---
dll/win32/lpk/CMakeLists.txt | 2 +-
dll/win32/lpk/bidi.c | 2 --
dll/win32/lpk/lpk.c | 55 ++++++++++++++++++++++++++++++++++++--
dll/win32/lpk/ros_lpk.h | 2 ++
dll/win32/lpk/stub.c | 1 +
win32ss/gdi/gdi32/include/gdi32p.h | 15 +++++++++--
win32ss/gdi/gdi32/main/dllmain.c | 1 +
win32ss/gdi/gdi32/misc/misc.c | 28 ++++++++++++++++---
win32ss/gdi/gdi32/objects/utils.c | 3 +++
9 files changed, 99 insertions(+), 10 deletions(-)
diff --git a/dll/win32/lpk/CMakeLists.txt b/dll/win32/lpk/CMakeLists.txt
index 858e468bc4..9f4c504cb0 100644
--- a/dll/win32/lpk/CMakeLists.txt
+++ b/dll/win32/lpk/CMakeLists.txt
@@ -18,6 +18,6 @@ set_module_type(lpk win32dll UNICODE)
target_link_libraries(lpk wine)
-add_importlibs(lpk usp10 user32 gdi32 msvcrt kernel32 ntdll)
+add_importlibs(lpk usp10 version user32 gdi32 msvcrt kernel32 ntdll)
add_pch(lpk ros_lpk.h SOURCE)
add_cd_file(TARGET lpk DESTINATION reactos/system32 FOR all)
diff --git a/dll/win32/lpk/bidi.c b/dll/win32/lpk/bidi.c
index 1d92cfd002..1a38c595aa 100644
--- a/dll/win32/lpk/bidi.c
+++ b/dll/win32/lpk/bidi.c
@@ -43,8 +43,6 @@
*/
#include "ros_lpk.h"
-#include "wine/unicode.h"
-#include "wine/debug.h"
//#include "config.h"
//#include "gdi_private.h"
diff --git a/dll/win32/lpk/lpk.c b/dll/win32/lpk/lpk.c
index 2bbb744c88..f78015447d 100644
--- a/dll/win32/lpk/lpk.c
+++ b/dll/win32/lpk/lpk.c
@@ -7,7 +7,8 @@
*/
#include "ros_lpk.h"
-#include <debug.h>
+
+WINE_DEFAULT_DEBUG_CHANNEL(bidi);
LPK_LPEDITCONTROL_LIST LpkEditControl = {EditCreate, EditIchToXY, EditMouseToIch,
EditCchInWidth,
EditGetLineWidth, EditDrawText, EditHScroll,
EditMoveSelection,
@@ -109,6 +110,55 @@ static void LPK_DrawUnderscore(HDC hdc, int x, int y, LPCWSTR str,
int count, in
DeleteObject(hpen);
}
+/* Code taken from the GetProcessDefaultLayout function from Wine's user32
+ * Wine version 3.17
+ *
+ * This function should be called from LpkInitialize,
+ * which is in turn called by GdiInitializeLanguagePack (from gdi32).
+ * TODO: Move call from LpkDllInitialize to LpkInitialize when latter
+ * function is implemented.
+ */
+static void LPK_ApplyMirroring()
+{
+ static const WCHAR translationW[] = {
'\\','V','a','r','F','i','l','e','I','n','f','o',
+
'\\','T','r','a','n','s','l','a','t','i','o','n',
0 };
+ static const WCHAR filedescW[] = {
'\\','S','t','r','i','n','g','F','i','l','e','I','n','f','o',
+
'\\','%','0','4','x','%','0','4','x',
+
'\\','F','i','l','e','D','e','s','c','r','i','p','t','i','o','n',0
};
+ WCHAR *str, buffer[MAX_PATH];
+#ifdef __REACTOS__
+ DWORD i, version_layout = 0;
+ UINT len;
+#else
+ DWORD i, len, version_layout = 0;
+#endif
+ DWORD user_lang = GetUserDefaultLangID();
+ DWORD *languages;
+ void *data = NULL;
+
+ GetModuleFileNameW( 0, buffer, MAX_PATH );
+ if (!(len = GetFileVersionInfoSizeW( buffer, NULL ))) goto done;
+ if (!(data = HeapAlloc( GetProcessHeap(), 0, len ))) goto done;
+ if (!GetFileVersionInfoW( buffer, 0, len, data )) goto done;
+ if (!VerQueryValueW( data, translationW, (void **)&languages, &len ) || !len)
goto done;
+
+ len /= sizeof(DWORD);
+ for (i = 0; i < len; i++) if (LOWORD(languages[i]) == user_lang) break;
+ if (i == len) /* try neutral language */
+ for (i = 0; i < len; i++)
+ if (LOWORD(languages[i]) == MAKELANGID( PRIMARYLANGID(user_lang), SUBLANG_NEUTRAL
)) break;
+ if (i == len) i = 0; /* default to the first one */
+
+ sprintfW( buffer, filedescW, LOWORD(languages[i]), HIWORD(languages[i]) );
+ if (!VerQueryValueW( data, buffer, (void **)&str, &len )) goto done;
+ TRACE( "found description %s\n", debugstr_w( str ));
+ if (str[0] == 0x200e && str[1] == 0x200e) version_layout = LAYOUT_RTL;
+
+done:
+ HeapFree( GetProcessHeap(), 0, data );
+ SetProcessDefaultLayout(version_layout);
+}
+
BOOL
WINAPI
DllMain(
@@ -133,6 +183,7 @@ LpkDllInitialize(
DisableThreadLibraryCalls(hDll);
/* Tell usp10 it is activated usp10 */
//LpkPresent();
+ LPK_ApplyMirroring();
break;
default:
@@ -202,7 +253,7 @@ LpkExtTextOut(
}
else
{
- DPRINT1("BIDI_Reorder failed, falling back to original
string.\n");
+ WARN("BIDI_Reorder failed, falling back to original string.\n");
bResult = ExtTextOutW(hdc, x, y, fuOptions, lprc, lpString, uCount, lpDx);
}
diff --git a/dll/win32/lpk/ros_lpk.h b/dll/win32/lpk/ros_lpk.h
index ecb3ef91fc..2d2d338080 100644
--- a/dll/win32/lpk/ros_lpk.h
+++ b/dll/win32/lpk/ros_lpk.h
@@ -18,6 +18,8 @@
#include <winnls.h>
#include <usp10.h>
#include <strsafe.h>
+#include "wine/unicode.h"
+#include "wine/debug.h"
/* FIXME USP10 api that does not have prototype in any include file */
VOID WINAPI LpkPresent(VOID);
diff --git a/dll/win32/lpk/stub.c b/dll/win32/lpk/stub.c
index b601a35868..310c4caf94 100644
--- a/dll/win32/lpk/stub.c
+++ b/dll/win32/lpk/stub.c
@@ -10,6 +10,7 @@
#include <stubs.h>
+#undef UNIMPLEMENTED
#define UNIMPLEMENTED DbgPrint("LPK: %s is unimplemented, please try again
later.\n", __FUNCTION__);
/*
diff --git a/win32ss/gdi/gdi32/include/gdi32p.h b/win32ss/gdi/gdi32/include/gdi32p.h
index c78f993d22..9dc2ec4fb6 100644
--- a/win32ss/gdi/gdi32/include/gdi32p.h
+++ b/win32ss/gdi/gdi32/include/gdi32p.h
@@ -64,8 +64,9 @@ extern LPKGCP LpkGetCharacterPlacement;
#define SAPCALLBACKDELAY 244
-#define LPK_ETO 1
-#define LPK_GCP 2
+#define LPK_INIT 1
+#define LPK_ETO 2
+#define LPK_GCP 3
/* MACRO ********************************************************************/
@@ -319,6 +320,16 @@ LoadLPK(
INT LpkFunctionID
);
+VOID
+WINAPI
+GdiInitializeLanguagePack(
+ _In_ DWORD InitParam);
+
+VOID
+WINAPI
+InitializeLpkHooks(
+ _In_ FARPROC *hookfuncs);
+
BOOL
WINAPI
GetETM(HDC hdc,
diff --git a/win32ss/gdi/gdi32/main/dllmain.c b/win32ss/gdi/gdi32/main/dllmain.c
index 0e34df29db..b59dfbe421 100644
--- a/win32ss/gdi/gdi32/main/dllmain.c
+++ b/win32ss/gdi/gdi32/main/dllmain.c
@@ -51,6 +51,7 @@ GdiProcessSetup(VOID)
GdiHandleCache =
(PGDIHANDLECACHE)NtCurrentTeb()->ProcessEnvironmentBlock->GdiHandleBuffer;
RtlInitializeCriticalSection(&semLocal);
InitializeCriticalSection(&gcsClientObjLinks);
+ GdiInitializeLanguagePack(0);
}
VOID
diff --git a/win32ss/gdi/gdi32/misc/misc.c b/win32ss/gdi/gdi32/misc/misc.c
index 6675e7335c..b31db63b9f 100644
--- a/win32ss/gdi/gdi32/misc/misc.c
+++ b/win32ss/gdi/gdi32/misc/misc.c
@@ -1021,12 +1021,34 @@ GdiRealizationInfo(HDC hdc,
/*
- * @unimplemented
+ * @halfplemented
*/
VOID WINAPI GdiInitializeLanguagePack(DWORD InitParam)
{
- UNIMPLEMENTED;
- SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+ /* Lpk function pointers to be passed to user32 */
+#if 0
+ FARPROC hookfuncs[4];
+#endif
+
+#ifdef LANGPACK
+ if (!LoadLPK(LPK_INIT)) // no lpk found!
+#endif
+ return;
+
+ /* Call InitializeLpkHooks with 4 procedure addresses
+ loaded from lpk.dll but currently only one of them is currently implemented.
+ Then InitializeLpkHooks (in user32) uses these to replace certain internal
functions
+ and ORs a DWORD being used also by ClientThreadSetup and calls
+ NtUserOneParam with parameter 54 which is ONEPARAM_ROUTINE_REGISTERLPK
+ which most likely changes the value of dwLpkEntryPoints in the
+ PROCESSINFO struct */
+
+#if 0
+ hookfuncs[0] = GetProcAddress(hLpk, "LpkPSMTextOut");
+ InitializeLpkHooks(hookfuncs);
+#endif
+
+ gbLpk = TRUE;
}
BOOL
diff --git a/win32ss/gdi/gdi32/objects/utils.c b/win32ss/gdi/gdi32/objects/utils.c
index 432c6e1482..d594b46cb6 100644
--- a/win32ss/gdi/gdi32/objects/utils.c
+++ b/win32ss/gdi/gdi32/objects/utils.c
@@ -428,6 +428,9 @@ BOOL WINAPI LoadLPK(INT LpkFunctionID)
{
switch (LpkFunctionID)
{
+ case LPK_INIT:
+ return TRUE;
+
case LPK_ETO:
if (!LpkExtTextOut) // Check if the function is already loaded
LpkExtTextOut = (LPKETO) GetProcAddress(hLpk,
"LpkExtTextOut");