diff --git a/dll/win32/lpk/CMakeLists.txt b/dll/win32/lpk/CMakeLists.txt index 858e468bc48..9f4c504cb02 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 1d92cfd0021..1a38c595aa0 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 2bbb744c88c..f78015447d2 100644 --- a/dll/win32/lpk/lpk.c +++ b/dll/win32/lpk/lpk.c @@ -7,7 +7,8 @@ */ #include "ros_lpk.h" -#include + +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 ecb3ef91fc5..2d2d3380800 100644 --- a/dll/win32/lpk/ros_lpk.h +++ b/dll/win32/lpk/ros_lpk.h @@ -18,6 +18,8 @@ #include #include #include +#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 b601a358682..310c4caf946 100644 --- a/dll/win32/lpk/stub.c +++ b/dll/win32/lpk/stub.c @@ -10,6 +10,7 @@ #include +#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 c78f993d223..9dc2ec4fb6b 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 0e34df29db9..b59dfbe4210 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 6675e7335cc..b31db63b9fa 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 432c6e1482a..d594b46cb6d 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");