[PATCH v3 0/7] MR10090: kernelbase/loader.c: Include rudimentary support for multilanguage resource inclusion.
For programs that rely on language specific data for resources such as menus and text, attempt to search for and associated "mui" file. For example, if program "myapp.exe" is executed and resources are not found, and the user's language ID is "ENU", search for file "myapp.ENU", and if found, utilize that file for the source of resource data. -- v3: kernelbase/loader.c: Add and refine the rudimentary support for multi-language resource retrieval. kernelbase/loader.c: Add rudimentary support for multiplanguage resource inclusion. Merge branch 'master' of https://gitlab.winehq.org/NoDakker/wine-mui-no-dakker kernelbase/loader.c: Add rudimentary multi-language resource support. kernelbase: Add rudimentary support for multilanguage resource retrieval kernelbase/loader.c: Include rudimentary support for multilanguage resource inclusion. kernelbase: Add rudimentary support for multilanguage resource retrieval kernelbase/loader.c: Include rudimentary support for multilanguage resource inclusion. https://gitlab.winehq.org/wine/wine/-/merge_requests/10090
From: Craig Schulstad <craigaschulstad@gmail.com> For programs that rely on language specific data for resources such as menus and text, attempt to search for and associated "mui" file. For example, if program "myapp.exe" is executed and resources are not found, and the user's language ID is "ENU", search for file "myapp.ENU", and if found, utilize that file for the source of resource data. --- dlls/kernelbase/loader.c | 179 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 172 insertions(+), 7 deletions(-) mode change 100644 => 100755 dlls/kernelbase/loader.c diff --git a/dlls/kernelbase/loader.c b/dlls/kernelbase/loader.c old mode 100644 new mode 100755 index 34767ab4a7b..f6bc614ea65 --- a/dlls/kernelbase/loader.c +++ b/dlls/kernelbase/loader.c @@ -56,6 +56,10 @@ static CRITICAL_SECTION_DEBUG critsect_debug = }; static CRITICAL_SECTION exclusive_datafile_list_section = { &critsect_debug, -1, 0, 0, 0, 0 }; +static WCHAR mui_locale[LOCALE_NAME_MAX_LENGTH]; /* MUI work variables */ +static BOOL locale_found = FALSE; +static BOOL recursion_flag = FALSE; + /*********************************************************************** * Modules ***********************************************************************/ @@ -1056,11 +1060,125 @@ BOOL WINAPI DECLSPEC_HOTPATCH EnumResourceTypesExW( HMODULE module, ENUMRESTYPEP return ret; } +/***********************************************************************/ +/* get_mui - Acquire an MUI module for the associated resource */ +/***********************************************************************/ + +HMODULE get_mui(HMODULE module) + +{ + HMODULE mui_module = NULL; + + WCHAR module_name[MAX_PATH], mui_name[MAX_PATH]; + + INT i, j, k, l; + + /* Initialize the work strings */ + + for (i = 0; i < MAX_PATH; i++) { + module_name[i] = 0; + mui_name[i] = 0; + } + + /* Note - the reference to the Windows file name for an "MUI" file has a structure such as */ + /* "C:\Program Files\Application Directory\xx-XX\Application.exe.mui"; however, in testing */ + /* out the usage of the "GetModuleFileNameW" function, it was determined that it works with */ + /* a relative Linux file structure such as "xx-XX/Application.exe.mui". */ + + if (!(GetModuleFileNameW(module, module_name, MAX_PATH))) /* Acquire the base resource file name */ + return module; + + /* Stay with the original module reference if this file is not an executable file. */ + + if (!(wcsstr(module_name, L".exe"))) + return module; + + /* Acquire the locale name using LCIDToLocaleName. Since this function utilizes the FindResourceExW function, this */ + /* sets up a recursive call to this function. In order to avoid a stack overflow condition that would be caused by */ + /* repeated calls, a flag will be set on to return back to the FindResourceExW function without again calling the */ + /* locale acquisition function. */ + + if (!(locale_found)) { + + if (recursion_flag) + return module; + + recursion_flag = TRUE; + + LCIDToLocaleName( GetUserDefaultLCID(), mui_locale, LOCALE_NAME_MAX_LENGTH, 0 ); + + recursion_flag = FALSE; + + locale_found = TRUE; + + } + + /* Locate the position of the final backslash in the retrieved executable file. */ + + j = 0; + + for (i = 0; i < MAX_PATH; i++) { + + if (module_name[i] == 0) + break; + + if (module_name[i] == '\\') + j = i; + } + + /* Set up the work index that will be used to extract just the executable file from the fully qualified file name. */ + + k = 0; + + for (i = 0; i < MAX_PATH; i++) { + + if (module_name[i] == 0) + break; + + /* If work index "j" has been set to -1, then the file portion of the qualified name has been reached and will */ + /* be copied to the "MUI" file reference. */ + + if (j < 0) { + mui_name[k] = module_name[i]; + k++; + } + + /* When the position of the final backslash has been reached, add the locale name as the folder/directory */ + /* containing the "MUI" file and reset work index "j" to -1. */ + + if (i >= j && j > 0) { + for (l = 0; l < 5; l++) { + mui_name[k] = mui_locale[l]; + k++; + } + mui_name[k] = '/'; + k++; + j = -1; + } + } + + /* Finally, append the literal ".mui" onto the file reference. */ + + wcscat(mui_name, L".mui"); + + /* Now, see if there is an associated "MUI" file and if so use its handle for the module handle. */ + + mui_module = LoadLibraryExW(mui_name, 0, 0); + + if (mui_module) { + return mui_module; + } else { + return module; + } + +} + +/***********************************************************************/ +/* get_res_handle - Isolated call of the LdrFindResource function */ +/***********************************************************************/ + +HRSRC get_res_handle(HMODULE module, LPCWSTR type, LPCWSTR name, WORD lang) -/********************************************************************** - * FindResourceExW (kernelbase.@) - */ -HRSRC WINAPI DECLSPEC_HOTPATCH FindResourceExW( HMODULE module, LPCWSTR type, LPCWSTR name, WORD lang ) { NTSTATUS status; UNICODE_STRING nameW, typeW; @@ -1069,7 +1187,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 @@ -1091,9 +1208,41 @@ 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; + + TRACE( "%p %s %s %04x\n", module, debugstr_w(type), debugstr_w(name), lang ); + + if (!module) module = GetModuleHandleW( 0 ); + + rsrc = get_res_handle(module, type, name, lang); + + if (rsrc) { + + return rsrc; + + } else { + + /* If a resource retrieval failed using the initial module value, attempt to */ + /* locate an associated MUI file and retry the resource retrieval. */ + + module = get_mui(module); + + rsrc = get_res_handle(module, type, name, lang); + + return rsrc; + + } +} /********************************************************************** * FindResourceW (kernelbase.@) @@ -1120,10 +1269,26 @@ HGLOBAL WINAPI DECLSPEC_HOTPATCH LoadResource( HINSTANCE module, HRSRC rsrc ) { void *ret; + HMODULE mui_module = NULL; + TRACE( "%p %p\n", module, rsrc ); - if (!rsrc) return 0; - if (!module) module = GetModuleHandleW( 0 ); + if (!rsrc) + return 0; + + if (!module) + module = GetModuleHandleW( 0 ); + + /* Only check for an MUI reference if the resource handle value is less than the module value, */ + /* or if an MUI reference was found and the MUI reference and handle value are larger than the */ + /* module value for the executable file. That is a signal that the resource handle is to be */ + /* associated with the MUI file instead of the executable file. */ + + mui_module = get_mui(module); + + if (((HMODULE)rsrc < module) || ((mui_module > module) && ((HMODULE)rsrc > mui_module))) + module = mui_module; + if (!set_ntstatus( LdrAccessResource( module, (IMAGE_RESOURCE_DATA_ENTRY *)rsrc, &ret, NULL ))) return 0; return ret; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10090
From: Craig Schulstad <craigaschulstad@gmail.com> Within the loader.c module, additional functions are called to search for an associated "mui" file that contains resources for menus, menu items, dialog boxes, and similar resources. --- dlls/kernelbase/loader.c | 135 +++++++++++++++++---------------------- 1 file changed, 58 insertions(+), 77 deletions(-) diff --git a/dlls/kernelbase/loader.c b/dlls/kernelbase/loader.c index f6bc614ea65..9bcf315c103 100755 --- a/dlls/kernelbase/loader.c +++ b/dlls/kernelbase/loader.c @@ -20,6 +20,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ + #include <stdarg.h> #include "ntstatus.h" @@ -56,7 +57,7 @@ static CRITICAL_SECTION_DEBUG critsect_debug = }; static CRITICAL_SECTION exclusive_datafile_list_section = { &critsect_debug, -1, 0, 0, 0, 0 }; -static WCHAR mui_locale[LOCALE_NAME_MAX_LENGTH]; /* MUI work variables */ +static WCHAR mui_locale[LOCALE_NAME_MAX_LENGTH]; static BOOL locale_found = FALSE; static BOOL recursion_flag = FALSE; @@ -1060,16 +1061,15 @@ BOOL WINAPI DECLSPEC_HOTPATCH EnumResourceTypesExW( HMODULE module, ENUMRESTYPEP return ret; } + /***********************************************************************/ /* get_mui - Acquire an MUI module for the associated resource */ /***********************************************************************/ HMODULE get_mui(HMODULE module) - { - HMODULE mui_module = NULL; - WCHAR module_name[MAX_PATH], mui_name[MAX_PATH]; + HMODULE mui_module; INT i, j, k, l; @@ -1080,28 +1080,15 @@ HMODULE get_mui(HMODULE module) mui_name[i] = 0; } - /* Note - the reference to the Windows file name for an "MUI" file has a structure such as */ - /* "C:\Program Files\Application Directory\xx-XX\Application.exe.mui"; however, in testing */ - /* out the usage of the "GetModuleFileNameW" function, it was determined that it works with */ - /* a relative Linux file structure such as "xx-XX/Application.exe.mui". */ - - if (!(GetModuleFileNameW(module, module_name, MAX_PATH))) /* Acquire the base resource file name */ - return module; + /* Acquire the base resource file name */ - /* Stay with the original module reference if this file is not an executable file. */ - - if (!(wcsstr(module_name, L".exe"))) - return module; - - /* Acquire the locale name using LCIDToLocaleName. Since this function utilizes the FindResourceExW function, this */ - /* sets up a recursive call to this function. In order to avoid a stack overflow condition that would be caused by */ - /* repeated calls, a flag will be set on to return back to the FindResourceExW function without again calling the */ - /* locale acquisition function. */ + if (!(GetModuleFileNameW(module, module_name, MAX_PATH))) + return module; if (!(locale_found)) { if (recursion_flag) - return module; + return module; recursion_flag = TRUE; @@ -1119,11 +1106,9 @@ HMODULE get_mui(HMODULE module) for (i = 0; i < MAX_PATH; i++) { - if (module_name[i] == 0) - break; + if (module_name[i] == 0) break; - if (module_name[i] == '\\') - j = i; + if (module_name[i] == '\\') j = i; } /* Set up the work index that will be used to extract just the executable file from the fully qualified file name. */ @@ -1132,19 +1117,18 @@ HMODULE get_mui(HMODULE module) for (i = 0; i < MAX_PATH; i++) { - if (module_name[i] == 0) - break; + if (module_name[i] == 0) break; - /* If work index "j" has been set to -1, then the file portion of the qualified name has been reached and will */ - /* be copied to the "MUI" file reference. */ + /* If work index "j" has been set to -1, then the file portion of the qualified */ + /* name has been reached and will be copied to the "MUI" file reference. */ if (j < 0) { mui_name[k] = module_name[i]; k++; } - /* When the position of the final backslash has been reached, add the locale name as the folder/directory */ - /* containing the "MUI" file and reset work index "j" to -1. */ + /* When the position of the final backslash has been reached, add the locale name as */ + /* the folder/directory containing the "MUI" file and reset work index "j" to -1. */ if (i >= j && j > 0) { for (l = 0; l < 5; l++) { @@ -1161,16 +1145,18 @@ HMODULE get_mui(HMODULE module) wcscat(mui_name, L".mui"); - /* Now, see if there is an associated "MUI" file and if so use its handle for the module handle. */ + /* Now, see if there is an associated "MUI" file and if so, use its handle for the module handle. */ mui_module = LoadLibraryExW(mui_name, 0, 0); + + if (mui_module != NULL) + TRACE("MUI module found: %s Address: %p\n", debugstr_w(module_name), mui_module); - if (mui_module) { + if (mui_module != NULL) return mui_module; - } else { + else return module; - } - + } /***********************************************************************/ @@ -1195,7 +1181,7 @@ HRSRC get_res_handle(HMODULE module, LPCWSTR type, LPCWSTR name, WORD lang) 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) ); @@ -1210,38 +1196,34 @@ HRSRC get_res_handle(HMODULE module, LPCWSTR type, LPCWSTR name, WORD lang) 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; - - TRACE( "%p %s %s %04x\n", module, debugstr_w(type), debugstr_w(name), lang ); + HMODULE work_module = NULL; + + TRACE( "FindResourceW: %p %s %s %04x\n", module, debugstr_w(type), debugstr_w(name), lang ); if (!module) module = GetModuleHandleW( 0 ); - - rsrc = get_res_handle(module, type, name, lang); - - if (rsrc) { - - return rsrc; - - } else { - - /* If a resource retrieval failed using the initial module value, attempt to */ - /* locate an associated MUI file and retry the resource retrieval. */ - - module = get_mui(module); - + + work_module = GetModuleHandleW( 0 ); + + if (module != work_module) { rsrc = get_res_handle(module, type, name, lang); + } else { + rsrc = get_res_handle(get_mui(module), type, name, lang); + + if (!rsrc) + TRACE("Resource not found from MUI\n"); + } + + return rsrc; - return rsrc; - - } } /********************************************************************** @@ -1269,29 +1251,28 @@ HGLOBAL WINAPI DECLSPEC_HOTPATCH LoadResource( HINSTANCE module, HRSRC rsrc ) { void *ret; - HMODULE mui_module = NULL; - - TRACE( "%p %p\n", module, rsrc ); - - if (!rsrc) - return 0; - - if (!module) - module = GetModuleHandleW( 0 ); - - /* Only check for an MUI reference if the resource handle value is less than the module value, */ - /* or if an MUI reference was found and the MUI reference and handle value are larger than the */ - /* module value for the executable file. That is a signal that the resource handle is to be */ - /* associated with the MUI file instead of the executable file. */ - - mui_module = get_mui(module); + HMODULE work_module = NULL; + + TRACE( "LoadResource: %p %p\n", module, rsrc ); - if (((HMODULE)rsrc < module) || ((mui_module > module) && ((HMODULE)rsrc > mui_module))) - module = mui_module; + if (!rsrc) return 0; + if (!module) module = GetModuleHandleW( 0 ); + + work_module = GetModuleHandleW( 0 ); + + if (module != work_module) { + if (!set_ntstatus( LdrAccessResource( module, (IMAGE_RESOURCE_DATA_ENTRY *)rsrc, &ret, NULL ))) + return 0; + return ret; + } - if (!set_ntstatus( LdrAccessResource( module, (IMAGE_RESOURCE_DATA_ENTRY *)rsrc, &ret, NULL ))) + if (!set_ntstatus( LdrAccessResource( get_mui(module), (IMAGE_RESOURCE_DATA_ENTRY *)rsrc, &ret, NULL ))) { + TRACE("Resource was not loaded\n"); return 0; + } + return ret; + } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10090
From: Craig Schulstad <craigaschulstad@gmail.com> For programs that rely on language specific data for resources such as menus and text, attempt to search for and associated "mui" file. For example, if program "myapp.exe" is executed and resources are not found, and the user's language ID is "ENU", search for file "myapp.ENU", and if found, utilize that file for the source of resource data. --- dlls/kernelbase/loader.c | 179 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 172 insertions(+), 7 deletions(-) mode change 100644 => 100755 dlls/kernelbase/loader.c diff --git a/dlls/kernelbase/loader.c b/dlls/kernelbase/loader.c old mode 100644 new mode 100755 index 34767ab4a7b..f6bc614ea65 --- a/dlls/kernelbase/loader.c +++ b/dlls/kernelbase/loader.c @@ -56,6 +56,10 @@ static CRITICAL_SECTION_DEBUG critsect_debug = }; static CRITICAL_SECTION exclusive_datafile_list_section = { &critsect_debug, -1, 0, 0, 0, 0 }; +static WCHAR mui_locale[LOCALE_NAME_MAX_LENGTH]; /* MUI work variables */ +static BOOL locale_found = FALSE; +static BOOL recursion_flag = FALSE; + /*********************************************************************** * Modules ***********************************************************************/ @@ -1056,11 +1060,125 @@ BOOL WINAPI DECLSPEC_HOTPATCH EnumResourceTypesExW( HMODULE module, ENUMRESTYPEP return ret; } +/***********************************************************************/ +/* get_mui - Acquire an MUI module for the associated resource */ +/***********************************************************************/ + +HMODULE get_mui(HMODULE module) + +{ + HMODULE mui_module = NULL; + + WCHAR module_name[MAX_PATH], mui_name[MAX_PATH]; + + INT i, j, k, l; + + /* Initialize the work strings */ + + for (i = 0; i < MAX_PATH; i++) { + module_name[i] = 0; + mui_name[i] = 0; + } + + /* Note - the reference to the Windows file name for an "MUI" file has a structure such as */ + /* "C:\Program Files\Application Directory\xx-XX\Application.exe.mui"; however, in testing */ + /* out the usage of the "GetModuleFileNameW" function, it was determined that it works with */ + /* a relative Linux file structure such as "xx-XX/Application.exe.mui". */ + + if (!(GetModuleFileNameW(module, module_name, MAX_PATH))) /* Acquire the base resource file name */ + return module; + + /* Stay with the original module reference if this file is not an executable file. */ + + if (!(wcsstr(module_name, L".exe"))) + return module; + + /* Acquire the locale name using LCIDToLocaleName. Since this function utilizes the FindResourceExW function, this */ + /* sets up a recursive call to this function. In order to avoid a stack overflow condition that would be caused by */ + /* repeated calls, a flag will be set on to return back to the FindResourceExW function without again calling the */ + /* locale acquisition function. */ + + if (!(locale_found)) { + + if (recursion_flag) + return module; + + recursion_flag = TRUE; + + LCIDToLocaleName( GetUserDefaultLCID(), mui_locale, LOCALE_NAME_MAX_LENGTH, 0 ); + + recursion_flag = FALSE; + + locale_found = TRUE; + + } + + /* Locate the position of the final backslash in the retrieved executable file. */ + + j = 0; + + for (i = 0; i < MAX_PATH; i++) { + + if (module_name[i] == 0) + break; + + if (module_name[i] == '\\') + j = i; + } + + /* Set up the work index that will be used to extract just the executable file from the fully qualified file name. */ + + k = 0; + + for (i = 0; i < MAX_PATH; i++) { + + if (module_name[i] == 0) + break; + + /* If work index "j" has been set to -1, then the file portion of the qualified name has been reached and will */ + /* be copied to the "MUI" file reference. */ + + if (j < 0) { + mui_name[k] = module_name[i]; + k++; + } + + /* When the position of the final backslash has been reached, add the locale name as the folder/directory */ + /* containing the "MUI" file and reset work index "j" to -1. */ + + if (i >= j && j > 0) { + for (l = 0; l < 5; l++) { + mui_name[k] = mui_locale[l]; + k++; + } + mui_name[k] = '/'; + k++; + j = -1; + } + } + + /* Finally, append the literal ".mui" onto the file reference. */ + + wcscat(mui_name, L".mui"); + + /* Now, see if there is an associated "MUI" file and if so use its handle for the module handle. */ + + mui_module = LoadLibraryExW(mui_name, 0, 0); + + if (mui_module) { + return mui_module; + } else { + return module; + } + +} + +/***********************************************************************/ +/* get_res_handle - Isolated call of the LdrFindResource function */ +/***********************************************************************/ + +HRSRC get_res_handle(HMODULE module, LPCWSTR type, LPCWSTR name, WORD lang) -/********************************************************************** - * FindResourceExW (kernelbase.@) - */ -HRSRC WINAPI DECLSPEC_HOTPATCH FindResourceExW( HMODULE module, LPCWSTR type, LPCWSTR name, WORD lang ) { NTSTATUS status; UNICODE_STRING nameW, typeW; @@ -1069,7 +1187,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 @@ -1091,9 +1208,41 @@ 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; + + TRACE( "%p %s %s %04x\n", module, debugstr_w(type), debugstr_w(name), lang ); + + if (!module) module = GetModuleHandleW( 0 ); + + rsrc = get_res_handle(module, type, name, lang); + + if (rsrc) { + + return rsrc; + + } else { + + /* If a resource retrieval failed using the initial module value, attempt to */ + /* locate an associated MUI file and retry the resource retrieval. */ + + module = get_mui(module); + + rsrc = get_res_handle(module, type, name, lang); + + return rsrc; + + } +} /********************************************************************** * FindResourceW (kernelbase.@) @@ -1120,10 +1269,26 @@ HGLOBAL WINAPI DECLSPEC_HOTPATCH LoadResource( HINSTANCE module, HRSRC rsrc ) { void *ret; + HMODULE mui_module = NULL; + TRACE( "%p %p\n", module, rsrc ); - if (!rsrc) return 0; - if (!module) module = GetModuleHandleW( 0 ); + if (!rsrc) + return 0; + + if (!module) + module = GetModuleHandleW( 0 ); + + /* Only check for an MUI reference if the resource handle value is less than the module value, */ + /* or if an MUI reference was found and the MUI reference and handle value are larger than the */ + /* module value for the executable file. That is a signal that the resource handle is to be */ + /* associated with the MUI file instead of the executable file. */ + + mui_module = get_mui(module); + + if (((HMODULE)rsrc < module) || ((mui_module > module) && ((HMODULE)rsrc > mui_module))) + module = mui_module; + if (!set_ntstatus( LdrAccessResource( module, (IMAGE_RESOURCE_DATA_ENTRY *)rsrc, &ret, NULL ))) return 0; return ret; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10090
From: Craig Schulstad <craigaschulstad@gmail.com> Within the loader.c module, additional functions are called to search for an associated "mui" file that contains resources for menus, menu items, dialog boxes, and similar resources. --- dlls/kernelbase/loader.c | 135 +++++++++++++++++---------------------- 1 file changed, 58 insertions(+), 77 deletions(-) diff --git a/dlls/kernelbase/loader.c b/dlls/kernelbase/loader.c index f6bc614ea65..9bcf315c103 100755 --- a/dlls/kernelbase/loader.c +++ b/dlls/kernelbase/loader.c @@ -20,6 +20,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ + #include <stdarg.h> #include "ntstatus.h" @@ -56,7 +57,7 @@ static CRITICAL_SECTION_DEBUG critsect_debug = }; static CRITICAL_SECTION exclusive_datafile_list_section = { &critsect_debug, -1, 0, 0, 0, 0 }; -static WCHAR mui_locale[LOCALE_NAME_MAX_LENGTH]; /* MUI work variables */ +static WCHAR mui_locale[LOCALE_NAME_MAX_LENGTH]; static BOOL locale_found = FALSE; static BOOL recursion_flag = FALSE; @@ -1060,16 +1061,15 @@ BOOL WINAPI DECLSPEC_HOTPATCH EnumResourceTypesExW( HMODULE module, ENUMRESTYPEP return ret; } + /***********************************************************************/ /* get_mui - Acquire an MUI module for the associated resource */ /***********************************************************************/ HMODULE get_mui(HMODULE module) - { - HMODULE mui_module = NULL; - WCHAR module_name[MAX_PATH], mui_name[MAX_PATH]; + HMODULE mui_module; INT i, j, k, l; @@ -1080,28 +1080,15 @@ HMODULE get_mui(HMODULE module) mui_name[i] = 0; } - /* Note - the reference to the Windows file name for an "MUI" file has a structure such as */ - /* "C:\Program Files\Application Directory\xx-XX\Application.exe.mui"; however, in testing */ - /* out the usage of the "GetModuleFileNameW" function, it was determined that it works with */ - /* a relative Linux file structure such as "xx-XX/Application.exe.mui". */ - - if (!(GetModuleFileNameW(module, module_name, MAX_PATH))) /* Acquire the base resource file name */ - return module; + /* Acquire the base resource file name */ - /* Stay with the original module reference if this file is not an executable file. */ - - if (!(wcsstr(module_name, L".exe"))) - return module; - - /* Acquire the locale name using LCIDToLocaleName. Since this function utilizes the FindResourceExW function, this */ - /* sets up a recursive call to this function. In order to avoid a stack overflow condition that would be caused by */ - /* repeated calls, a flag will be set on to return back to the FindResourceExW function without again calling the */ - /* locale acquisition function. */ + if (!(GetModuleFileNameW(module, module_name, MAX_PATH))) + return module; if (!(locale_found)) { if (recursion_flag) - return module; + return module; recursion_flag = TRUE; @@ -1119,11 +1106,9 @@ HMODULE get_mui(HMODULE module) for (i = 0; i < MAX_PATH; i++) { - if (module_name[i] == 0) - break; + if (module_name[i] == 0) break; - if (module_name[i] == '\\') - j = i; + if (module_name[i] == '\\') j = i; } /* Set up the work index that will be used to extract just the executable file from the fully qualified file name. */ @@ -1132,19 +1117,18 @@ HMODULE get_mui(HMODULE module) for (i = 0; i < MAX_PATH; i++) { - if (module_name[i] == 0) - break; + if (module_name[i] == 0) break; - /* If work index "j" has been set to -1, then the file portion of the qualified name has been reached and will */ - /* be copied to the "MUI" file reference. */ + /* If work index "j" has been set to -1, then the file portion of the qualified */ + /* name has been reached and will be copied to the "MUI" file reference. */ if (j < 0) { mui_name[k] = module_name[i]; k++; } - /* When the position of the final backslash has been reached, add the locale name as the folder/directory */ - /* containing the "MUI" file and reset work index "j" to -1. */ + /* When the position of the final backslash has been reached, add the locale name as */ + /* the folder/directory containing the "MUI" file and reset work index "j" to -1. */ if (i >= j && j > 0) { for (l = 0; l < 5; l++) { @@ -1161,16 +1145,18 @@ HMODULE get_mui(HMODULE module) wcscat(mui_name, L".mui"); - /* Now, see if there is an associated "MUI" file and if so use its handle for the module handle. */ + /* Now, see if there is an associated "MUI" file and if so, use its handle for the module handle. */ mui_module = LoadLibraryExW(mui_name, 0, 0); + + if (mui_module != NULL) + TRACE("MUI module found: %s Address: %p\n", debugstr_w(module_name), mui_module); - if (mui_module) { + if (mui_module != NULL) return mui_module; - } else { + else return module; - } - + } /***********************************************************************/ @@ -1195,7 +1181,7 @@ HRSRC get_res_handle(HMODULE module, LPCWSTR type, LPCWSTR name, WORD lang) 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) ); @@ -1210,38 +1196,34 @@ HRSRC get_res_handle(HMODULE module, LPCWSTR type, LPCWSTR name, WORD lang) 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; - - TRACE( "%p %s %s %04x\n", module, debugstr_w(type), debugstr_w(name), lang ); + HMODULE work_module = NULL; + + TRACE( "FindResourceW: %p %s %s %04x\n", module, debugstr_w(type), debugstr_w(name), lang ); if (!module) module = GetModuleHandleW( 0 ); - - rsrc = get_res_handle(module, type, name, lang); - - if (rsrc) { - - return rsrc; - - } else { - - /* If a resource retrieval failed using the initial module value, attempt to */ - /* locate an associated MUI file and retry the resource retrieval. */ - - module = get_mui(module); - + + work_module = GetModuleHandleW( 0 ); + + if (module != work_module) { rsrc = get_res_handle(module, type, name, lang); + } else { + rsrc = get_res_handle(get_mui(module), type, name, lang); + + if (!rsrc) + TRACE("Resource not found from MUI\n"); + } + + return rsrc; - return rsrc; - - } } /********************************************************************** @@ -1269,29 +1251,28 @@ HGLOBAL WINAPI DECLSPEC_HOTPATCH LoadResource( HINSTANCE module, HRSRC rsrc ) { void *ret; - HMODULE mui_module = NULL; - - TRACE( "%p %p\n", module, rsrc ); - - if (!rsrc) - return 0; - - if (!module) - module = GetModuleHandleW( 0 ); - - /* Only check for an MUI reference if the resource handle value is less than the module value, */ - /* or if an MUI reference was found and the MUI reference and handle value are larger than the */ - /* module value for the executable file. That is a signal that the resource handle is to be */ - /* associated with the MUI file instead of the executable file. */ - - mui_module = get_mui(module); + HMODULE work_module = NULL; + + TRACE( "LoadResource: %p %p\n", module, rsrc ); - if (((HMODULE)rsrc < module) || ((mui_module > module) && ((HMODULE)rsrc > mui_module))) - module = mui_module; + if (!rsrc) return 0; + if (!module) module = GetModuleHandleW( 0 ); + + work_module = GetModuleHandleW( 0 ); + + if (module != work_module) { + if (!set_ntstatus( LdrAccessResource( module, (IMAGE_RESOURCE_DATA_ENTRY *)rsrc, &ret, NULL ))) + return 0; + return ret; + } - if (!set_ntstatus( LdrAccessResource( module, (IMAGE_RESOURCE_DATA_ENTRY *)rsrc, &ret, NULL ))) + if (!set_ntstatus( LdrAccessResource( get_mui(module), (IMAGE_RESOURCE_DATA_ENTRY *)rsrc, &ret, NULL ))) { + TRACE("Resource was not loaded\n"); return 0; + } + return ret; + } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10090
From: Craig Schulstad <craigaschulstad@gmail.com> Before attempting to find a resource, determine if there is an associated multi-language resource file base upon the user language and if such a file is found, also search the file for resource data such as menu items, dialog boxes, and so forth. --- dlls/kernelbase/loader.c | 92 +++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 40 deletions(-) diff --git a/dlls/kernelbase/loader.c b/dlls/kernelbase/loader.c index 9bcf315c103..3d2b179c071 100755 --- a/dlls/kernelbase/loader.c +++ b/dlls/kernelbase/loader.c @@ -60,6 +60,7 @@ static CRITICAL_SECTION exclusive_datafile_list_section = { &critsect_debug, -1, static WCHAR mui_locale[LOCALE_NAME_MAX_LENGTH]; static BOOL locale_found = FALSE; static BOOL recursion_flag = FALSE; +static HMODULE module_mui = NULL; /*********************************************************************** * Modules @@ -1069,9 +1070,8 @@ BOOL WINAPI DECLSPEC_HOTPATCH EnumResourceTypesExW( HMODULE module, ENUMRESTYPEP HMODULE get_mui(HMODULE module) { WCHAR module_name[MAX_PATH], mui_name[MAX_PATH]; - HMODULE mui_module; - - INT i, j, k, l; + HMODULE mui_module = NULL; + INT i, j = 0, k = 0, l = 0; /* Initialize the work strings */ @@ -1082,13 +1082,20 @@ HMODULE get_mui(HMODULE module) /* Acquire the base resource file name */ - if (!(GetModuleFileNameW(module, module_name, MAX_PATH))) - return module; + if (!(GetModuleFileNameW(module, module_name, MAX_PATH))) { + TRACE ("Module file name was not found - returning with source module\n"); + return module; + } + + /* Stay with the original module reference if this file is not an executable file. */ + + if (!(wcsstr(module_name, L".exe"))) + return module; if (!(locale_found)) { if (recursion_flag) - return module; + return module; recursion_flag = TRUE; @@ -1102,8 +1109,6 @@ HMODULE get_mui(HMODULE module) /* Locate the position of the final backslash in the retrieved executable file. */ - j = 0; - for (i = 0; i < MAX_PATH; i++) { if (module_name[i] == 0) break; @@ -1113,8 +1118,6 @@ HMODULE get_mui(HMODULE module) /* Set up the work index that will be used to extract just the executable file from the fully qualified file name. */ - k = 0; - for (i = 0; i < MAX_PATH; i++) { if (module_name[i] == 0) break; @@ -1149,13 +1152,13 @@ HMODULE get_mui(HMODULE module) mui_module = LoadLibraryExW(mui_name, 0, 0); - if (mui_module != NULL) - TRACE("MUI module found: %s Address: %p\n", debugstr_w(module_name), mui_module); - - if (mui_module != NULL) + if (mui_module != NULL) { + module_mui = mui_module; return mui_module; - else + } else { + module_mui = NULL; return module; + } } @@ -1184,7 +1187,8 @@ HRSRC get_res_handle(HMODULE module, LPCWSTR type, LPCWSTR name, WORD 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 { @@ -1198,31 +1202,40 @@ HRSRC get_res_handle(HMODULE module, LPCWSTR type, LPCWSTR name, WORD lang) return (HRSRC)entry; } + /********************************************************************** * FindResourceExW (kernelbase.@) */ HRSRC WINAPI DECLSPEC_HOTPATCH FindResourceExW( HMODULE module, LPCWSTR type, LPCWSTR name, WORD lang ) { - HRSRC rsrc; - HMODULE work_module = NULL; - - TRACE( "FindResourceW: %p %s %s %04x\n", module, debugstr_w(type), debugstr_w(name), lang ); + HRSRC rsrc; + HMODULE work_module = NULL, test_module = NULL; if (!module) module = GetModuleHandleW( 0 ); - work_module = GetModuleHandleW( 0 ); + work_module = GetModuleHandleW( 0 ); - if (module != work_module) { + if (module != work_module) { rsrc = get_res_handle(module, type, name, lang); - } else { - rsrc = get_res_handle(get_mui(module), type, name, lang); - - if (!rsrc) - TRACE("Resource not found from MUI\n"); + 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; + return rsrc; } @@ -1250,26 +1263,25 @@ BOOL WINAPI DECLSPEC_HOTPATCH FreeResource( HGLOBAL handle ) HGLOBAL WINAPI DECLSPEC_HOTPATCH LoadResource( HINSTANCE module, HRSRC rsrc ) { void *ret; - - HMODULE work_module = NULL; - - TRACE( "LoadResource: %p %p\n", module, rsrc ); + HMODULE work_module = NULL; if (!rsrc) return 0; if (!module) module = GetModuleHandleW( 0 ); + work_module = module; - work_module = GetModuleHandleW( 0 ); + /* Check for and use a MUI module */ - if (module != work_module) { - if (!set_ntstatus( LdrAccessResource( module, (IMAGE_RESOURCE_DATA_ENTRY *)rsrc, &ret, NULL ))) - return 0; - return ret; + if (module_mui != NULL) { + if (((HMODULE)rsrc < module) || ((module_mui > module) && ((HMODULE)rsrc > module_mui))) + work_module = module_mui; } - if (!set_ntstatus( LdrAccessResource( get_mui(module), (IMAGE_RESOURCE_DATA_ENTRY *)rsrc, &ret, NULL ))) { - TRACE("Resource was not loaded\n"); + /* 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/10090
From: Craig Schulstad <craigaschulstad@gmail.com> --- dlls/kernelbase/loader.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dlls/kernelbase/loader.c b/dlls/kernelbase/loader.c index 3d2b179c071..8a385a05251 100755 --- a/dlls/kernelbase/loader.c +++ b/dlls/kernelbase/loader.c @@ -1226,7 +1226,8 @@ HRSRC WINAPI DECLSPEC_HOTPATCH FindResourceExW( HMODULE module, LPCWSTR type, LP module_mui = NULL; } else { rsrc = get_res_handle(test_module, type, name, lang); - + + /* Fall back to base exe file if resource was not found in the mui file */ 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); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10090
From: Craig Schulstad <craigaschulstad@gmail.com> This enhancement was refined to focus only on the retrieval of an associated mui file for the base exe file. --- dlls/kernelbase/loader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dlls/kernelbase/loader.c b/dlls/kernelbase/loader.c index 8a385a05251..c941aa93a2c 100755 --- a/dlls/kernelbase/loader.c +++ b/dlls/kernelbase/loader.c @@ -1228,7 +1228,7 @@ HRSRC WINAPI DECLSPEC_HOTPATCH FindResourceExW( HMODULE module, LPCWSTR type, LP rsrc = get_res_handle(test_module, type, name, lang); /* Fall back to base exe file if resource was not found in the mui file */ - if (!rsrc) { + 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; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10090
participants (2)
-
Craig Schulstad -
Craig Schulstad (@NoDakker)