Signed-off-by: Craig Schulstad <craigaschulstad(a)gmail.com>
---
dlls/kernelbase/loader.c | 169 +++++++++++++++++++++++++++++++++++++--
1 file changed, 164 insertions(+), 5 deletions(-)
diff --git a/dlls/kernelbase/loader.c b/dlls/kernelbase/loader.c
index fc9b0ce0083..0fbe9bcd9e8 100644
--- a/dlls/kernelbase/loader.c
+++ b/dlls/kernelbase/loader.c
@@ -48,6 +48,9 @@ struct exclusive_datafile
};
static struct list exclusive_datafile_list = LIST_INIT( exclusive_datafile_list );
+static WCHAR mui_locale[LOCALE_NAME_MAX_LENGTH];
+static BOOL locale_found = 0;
+static BOOL recursion_flag = 0;
/***********************************************************************
* Modules
@@ -1011,11 +1014,122 @@ 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". */
+
+ /* Acquire the base resource file name */
+
+ if (!(GetModuleFileNameW(module, module_name, MAX_PATH))) 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 = 1;
+
+ LCIDToLocaleName( GetUserDefaultLCID(), mui_locale, LOCALE_NAME_MAX_LENGTH, 0 );
+
+ recursion_flag = 0;
+
+ locale_found = 1;
+
+ }
+
+ /* 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;
@@ -1024,7 +1138,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
@@ -1046,7 +1159,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;
+
+ }
}
@@ -1074,11 +1221,23 @@ BOOL WINAPI DECLSPEC_HOTPATCH FreeResource( HGLOBAL handle )
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);
+
+ 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;
--
2.17.1