[PATCH v2 0/1] MR10575: kernelbase: Add language resource search functionality
For applications relying upon language specific resources, search for an associated language specific subfolder and mui file based upon the language in force for the prefix. -- v2: kernelbase: Add language resource search functionality https://gitlab.winehq.org/wine/wine/-/merge_requests/10575
From: Craig Schulstad <craigaschulstad@gmail.com> For applications relying upon language specific resources, search for an associated language specific subfolder and mui file based upon the language in force for the prefix. --- dlls/kernelbase/loader.c | 137 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 127 insertions(+), 10 deletions(-) diff --git a/dlls/kernelbase/loader.c b/dlls/kernelbase/loader.c index 6c6f1f31881..08d981e8393 100644 --- a/dlls/kernelbase/loader.c +++ b/dlls/kernelbase/loader.c @@ -33,6 +33,7 @@ #include "wine/asm.h" #include "wine/debug.h" #include "wine/exception.h" +#include "winreg.h" WINE_DEFAULT_DEBUG_CHANNEL(module); @@ -55,6 +56,9 @@ static CRITICAL_SECTION_DEBUG critsect_debug = }; static CRITICAL_SECTION exclusive_datafile_list_section = { &critsect_debug, -1, 0, 0, 0, 0 }; +static HMODULE module_mui = NULL; +static WCHAR mui_locale[LOCALE_NAME_MAX_LENGTH] = {L'\0'}; + /*********************************************************************** * Modules ***********************************************************************/ @@ -1063,10 +1067,71 @@ BOOL WINAPI DECLSPEC_HOTPATCH EnumResourceTypesExW( HMODULE module, ENUMRESTYPEP } -/********************************************************************** - * FindResourceExW (kernelbase.@) - */ -HRSRC WINAPI DECLSPEC_HOTPATCH FindResourceExW( HMODULE module, LPCWSTR type, LPCWSTR name, WORD lang ) +/***********************************************************************/ +/* get_mui - Acquire an MUI module for the associated resource */ +/***********************************************************************/ + +HMODULE get_mui(HMODULE module) +{ + WCHAR module_name[MAX_PATH], mui_name[MAX_PATH], * last_slash; + HMODULE mui_module = NULL; + HKEY intl_key; + DWORD count = LOCALE_NAME_MAX_LENGTH; + LONG save_error = GetLastError(); + + if (!(GetModuleFileNameW(module, module_name, MAX_PATH))) { + TRACE ("Module file name was not found - returning with source module\n"); + SetLastError(save_error); + return module; + } + + if (!(wcsstr(module_name, L".exe")) && !(wcsstr(module_name, L".EXE"))) return module; + + if (wcslen(mui_locale) == 0) { + RegCreateKeyExW( HKEY_CURRENT_USER, L"Control Panel\\International", + 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &intl_key, NULL ); + RegQueryValueExW( intl_key, L"LocaleName", NULL, NULL, (BYTE *)mui_locale, &count ); + TRACE("Locale name: %s\n", debugstr_w(mui_locale)); + } + + last_slash = wcsrchr(module_name, L'\\'); + + wcscpy(mui_name, module_name); + + mui_name[last_slash - module_name + 1] = L'\0'; + + wcscat(mui_name, mui_locale); + + wcscat(mui_name, last_slash); + + if (wcsstr(module_name, L".exe")) { + wcscat(mui_name, L".mui"); + } else { + wcscat(mui_name, L".MUI"); + } + + TRACE("Language path: %s\n", debugstr_w(mui_name)); + + mui_module = LoadLibraryExW(mui_name, 0, 0); + + SetLastError(save_error); + + if (mui_module != NULL) { + module_mui = mui_module; + return mui_module; + } else { + module_mui = NULL; + return module; + } + +} + +/***********************************************************************/ +/* get_res_handle - Isolated call of the LdrFindResource function */ +/***********************************************************************/ + +HRSRC get_res_handle(HMODULE module, LPCWSTR type, LPCWSTR name, WORD lang) + { NTSTATUS status; UNICODE_STRING nameW, typeW; @@ -1075,7 +1140,6 @@ HRSRC WINAPI DECLSPEC_HOTPATCH FindResourceExW( HMODULE module, LPCWSTR type, LP TRACE( "%p %s %s %04x\n", module, debugstr_w(type), debugstr_w(name), lang ); - if (!module) module = GetModuleHandleW( 0 ); nameW.Buffer = typeW.Buffer = NULL; __TRY @@ -1084,10 +1148,11 @@ HRSRC WINAPI DECLSPEC_HOTPATCH FindResourceExW( HMODULE module, LPCWSTR type, LP if ((status = get_res_nameW( type, &typeW )) != STATUS_SUCCESS) goto done; info.Type = (ULONG_PTR)typeW.Buffer; info.Name = (ULONG_PTR)nameW.Buffer; - info.Language = lang; + info.Language = lang; status = LdrFindResource_U( module, &info, 3, &entry ); done: - if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) ); + if (status != STATUS_SUCCESS) + SetLastError( RtlNtStatusToDosError(status) ); } __EXCEPT_PAGE_FAULT { @@ -1097,10 +1162,48 @@ HRSRC WINAPI DECLSPEC_HOTPATCH FindResourceExW( HMODULE module, LPCWSTR type, LP if (!IS_INTRESOURCE(nameW.Buffer)) HeapFree( GetProcessHeap(), 0, nameW.Buffer ); if (!IS_INTRESOURCE(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer ); + return (HRSRC)entry; } +/********************************************************************** + * FindResourceExW (kernelbase.@) + */ +HRSRC WINAPI DECLSPEC_HOTPATCH FindResourceExW( HMODULE module, LPCWSTR type, LPCWSTR name, WORD lang ) +{ + + HRSRC rsrc; + HMODULE work_module = NULL, test_module = NULL; + + if (!module) module = GetModuleHandleW( 0 ); + + work_module = GetModuleHandleW( 0 ); + + if (module != work_module) { + rsrc = get_res_handle(module, type, name, lang); + module_mui = NULL; + } else { + test_module = get_mui(module); + if (test_module == module) { + rsrc = get_res_handle(module, type, name, lang); + module_mui = NULL; + } else { + rsrc = get_res_handle(test_module, type, name, lang); + + if (!rsrc) { + TRACE("Fallback from MUI to base module: %p %p %s %s\n", test_module, module, debugstr_w(type), debugstr_w(name)); + rsrc = get_res_handle(module, type, name, lang); + module_mui = NULL; + } + } + } + + return rsrc; + +} + + /********************************************************************** * FindResourceW (kernelbase.@) */ @@ -1125,14 +1228,28 @@ BOOL WINAPI DECLSPEC_HOTPATCH FreeResource( HGLOBAL handle ) HGLOBAL WINAPI DECLSPEC_HOTPATCH LoadResource( HINSTANCE module, HRSRC rsrc ) { void *ret; - - TRACE( "%p %p\n", module, rsrc ); + HMODULE work_module = NULL; if (!rsrc) return 0; if (!module) module = GetModuleHandleW( 0 ); - if (!set_ntstatus( LdrAccessResource( module, (IMAGE_RESOURCE_DATA_ENTRY *)rsrc, &ret, NULL ))) + work_module = module; + + /* Check for and use a MUI module */ + + if (module_mui != NULL) { + if (((HMODULE)rsrc < module) || ((module_mui > module) && ((HMODULE)rsrc > module_mui))) + work_module = module_mui; + } + + /* Ready this handle for next resource retrieval */ + + module_mui= NULL; + + if (!set_ntstatus( LdrAccessResource( work_module, (IMAGE_RESOURCE_DATA_ENTRY *)rsrc, &ret, NULL ))) return 0; + return ret; + } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10575
This merge request was closed by Craig Schulstad. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10575
participants (2)
-
Craig Schulstad -
Craig Schulstad (@NoDakker)