[PATCH v6 0/9] MR10209: 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 "en-US", search for file "en-US/myapp.exe.mui", and if found, utilize that file for the source of resource data. -- v6: kernelbase/loader.c: Add rudimentary multilanguage resource support. https://gitlab.winehq.org/wine/wine/-/merge_requests/10209
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/10209
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/10209
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/10209
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/10209
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/10209
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/10209
From: Craig Schulstad <craigaschulstad@gmail.com> --- 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/10209
From: Craig Schulstad <craigaschulstad@gmail.com> --- 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 c941aa93a2c..3010e6cdea7 100755 --- a/dlls/kernelbase/loader.c +++ b/dlls/kernelbase/loader.c @@ -1234,7 +1234,7 @@ HRSRC WINAPI DECLSPEC_HOTPATCH FindResourceExW( HMODULE module, LPCWSTR type, LP module_mui = NULL; } } - } + } return rsrc; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10209
From: Craig Schulstad <craigaschulstad@gmail.com> Add a conditioned search for a mui file and subdirectory to enhance the finding of resources that might be language specific. --- dlls/kernelbase/loader.c | 1433 -------------------------------------- 1 file changed, 1433 deletions(-) delete mode 100755 dlls/kernelbase/loader.c diff --git a/dlls/kernelbase/loader.c b/dlls/kernelbase/loader.c deleted file mode 100755 index 3010e6cdea7..00000000000 --- a/dlls/kernelbase/loader.c +++ /dev/null @@ -1,1433 +0,0 @@ -/* - * Module loader - * - * Copyright 1993 Robert J. Amstadt - * Copyright 2006 Mike McCormack - * Copyright 1995, 2003, 2019 Alexandre Julliard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - - -#include <stdarg.h> - -#include "ntstatus.h" -#define WIN32_NO_STATUS -#include "windef.h" -#include "winbase.h" -#include "winnls.h" -#include "winternl.h" -#include "ddk/ntddk.h" -#include "kernelbase.h" -#include "wine/list.h" -#include "wine/asm.h" -#include "wine/debug.h" -#include "wine/exception.h" - -WINE_DEFAULT_DEBUG_CHANNEL(module); - - -/* to keep track of LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE file handles */ -struct exclusive_datafile -{ - struct list entry; - HMODULE module; - HANDLE file; -}; -static struct list exclusive_datafile_list = LIST_INIT( exclusive_datafile_list ); - -static CRITICAL_SECTION exclusive_datafile_list_section; -static CRITICAL_SECTION_DEBUG critsect_debug = -{ - 0, 0, &exclusive_datafile_list_section, - { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": exclusive_datafile_list_section") } -}; -static CRITICAL_SECTION exclusive_datafile_list_section = { &critsect_debug, -1, 0, 0, 0, 0 }; - -static WCHAR mui_locale[LOCALE_NAME_MAX_LENGTH]; -static BOOL locale_found = FALSE; -static BOOL recursion_flag = FALSE; -static HMODULE module_mui = NULL; - -/*********************************************************************** - * Modules - ***********************************************************************/ - - -/****************************************************************** - * get_proc_address - */ -FARPROC WINAPI get_proc_address( HMODULE module, LPCSTR function ) -{ - FARPROC proc; - ANSI_STRING str; - - if (!module) module = NtCurrentTeb()->Peb->ImageBaseAddress; - - if ((ULONG_PTR)function >> 16) - { - RtlInitAnsiString( &str, function ); - if (!set_ntstatus( LdrGetProcedureAddress( module, &str, 0, (void**)&proc ))) return NULL; - } - else if (!set_ntstatus( LdrGetProcedureAddress( module, NULL, LOWORD(function), (void**)&proc ))) - return NULL; - - return proc; -} - - -/****************************************************************** - * load_library_as_datafile - */ -static BOOL load_library_as_datafile( LPCWSTR load_path, DWORD flags, LPCWSTR name, HMODULE *mod_ret ) -{ - WCHAR filenameW[MAX_PATH]; - HANDLE mapping, file = INVALID_HANDLE_VALUE; - HMODULE module = 0; - DWORD protect = PAGE_READONLY; - - *mod_ret = 0; - - if (flags & LOAD_LIBRARY_AS_IMAGE_RESOURCE) protect |= SEC_IMAGE; - - if (SearchPathW( NULL, name, L".dll", ARRAY_SIZE( filenameW ), filenameW, NULL )) - { - file = CreateFileW( filenameW, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE, - NULL, OPEN_EXISTING, 0, 0 ); - } - if (file == INVALID_HANDLE_VALUE) return FALSE; - - mapping = CreateFileMappingW( file, NULL, protect, 0, 0, NULL ); - if (!mapping) goto failed; - - module = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 ); - CloseHandle( mapping ); - if (!module) goto failed; - - if (!(flags & LOAD_LIBRARY_AS_IMAGE_RESOURCE)) - { - /* make sure it's a valid PE file */ - if (!RtlImageNtHeader( module )) - { - SetLastError( ERROR_BAD_EXE_FORMAT ); - goto failed; - } - *mod_ret = (HMODULE)((char *)module + 1); /* set bit 0 for data file module */ - - if (flags & LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE) - { - struct exclusive_datafile *datafile = HeapAlloc( GetProcessHeap(), 0, sizeof(*datafile) ); - if (!datafile) goto failed; - datafile->module = *mod_ret; - datafile->file = file; - RtlEnterCriticalSection( &exclusive_datafile_list_section ); - list_add_head( &exclusive_datafile_list, &datafile->entry ); - RtlLeaveCriticalSection( &exclusive_datafile_list_section ); - TRACE( "delaying close %p for module %p\n", datafile->file, datafile->module ); - return TRUE; - } - } - else *mod_ret = (HMODULE)((char *)module + 2); /* set bit 1 for image resource module */ - - CloseHandle( file ); - return TRUE; - -failed: - if (module) UnmapViewOfFile( module ); - CloseHandle( file ); - return FALSE; -} - - -/****************************************************************** - * load_library - */ -static HMODULE load_library( const UNICODE_STRING *libname, DWORD flags ) -{ - const DWORD unsupported_flags = LOAD_IGNORE_CODE_AUTHZ_LEVEL | LOAD_LIBRARY_REQUIRE_SIGNED_TARGET; - const ULONG load_library_search_flags = LOAD_WITH_ALTERED_SEARCH_PATH | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR - | LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_USER_DIRS - | LOAD_LIBRARY_SEARCH_SYSTEM32 | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS; - NTSTATUS status; - HMODULE module; - WCHAR *load_path, *dummy; - DWORD load_flags = 0, search_flags; - - if (flags & unsupported_flags) FIXME( "unsupported flag(s) used %#08lx\n", flags ); - - if (flags & (LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE | - LOAD_LIBRARY_AS_IMAGE_RESOURCE)) - { - if (!set_ntstatus( LdrGetDllPath( libname->Buffer, flags, &load_path, &dummy ))) return 0; - if (LdrGetDllHandleEx( 0, load_path, NULL, libname, &module )) - load_library_as_datafile( load_path, flags, libname->Buffer, &module ); - RtlReleasePath( load_path ); - } - else - { - search_flags = flags & load_library_search_flags; - if (flags & DONT_RESOLVE_DLL_REFERENCES) load_flags |= LDR_DONT_RESOLVE_REFS; - status = LdrLoadDll( (void *)((ULONG_PTR)search_flags | 1), &load_flags, libname, &module ); - if (!set_ntstatus( status )) - { - module = 0; - if (status == STATUS_DLL_NOT_FOUND && (GetVersion() & 0x80000000)) - SetLastError( ERROR_DLL_NOT_FOUND ); - } - } - return module; -} - - -/**************************************************************************** - * AddDllDirectory (kernelbase.@) - */ -DLL_DIRECTORY_COOKIE WINAPI DECLSPEC_HOTPATCH AddDllDirectory( const WCHAR *dir ) -{ - UNICODE_STRING str; - void *cookie; - - RtlInitUnicodeString( &str, dir ); - if (!set_ntstatus( LdrAddDllDirectory( &str, &cookie ))) return NULL; - return cookie; -} - - -/*********************************************************************** - * DelayLoadFailureHook (kernelbase.@) - */ -FARPROC WINAPI DECLSPEC_HOTPATCH DelayLoadFailureHook( LPCSTR name, LPCSTR function ) -{ - ULONG_PTR args[2]; - - if ((ULONG_PTR)function >> 16) - ERR( "failed to delay load %s.%s\n", name, function ); - else - ERR( "failed to delay load %s.%u\n", name, LOWORD(function) ); - args[0] = (ULONG_PTR)name; - args[1] = (ULONG_PTR)function; - RaiseException( EXCEPTION_WINE_STUB, EXCEPTION_NONCONTINUABLE, 2, args ); - return NULL; -} - - -/**************************************************************************** - * DisableThreadLibraryCalls (kernelbase.@) - */ -BOOL WINAPI DECLSPEC_HOTPATCH DisableThreadLibraryCalls( HMODULE module ) -{ - return set_ntstatus( LdrDisableThreadCalloutsForDll( module )); -} - - -/*********************************************************************** - * FreeLibrary (kernelbase.@) - */ -BOOL WINAPI DECLSPEC_HOTPATCH FreeLibrary( HINSTANCE module ) -{ - if (!module) - { - SetLastError( ERROR_INVALID_HANDLE ); - return FALSE; - } - - if ((ULONG_PTR)module & 3) /* this is a datafile module */ - { - void *ptr = (void *)((ULONG_PTR)module & ~3); - if (!RtlImageNtHeader( ptr )) - { - SetLastError( ERROR_BAD_EXE_FORMAT ); - return FALSE; - } - if ((ULONG_PTR)module & 1) - { - struct exclusive_datafile *file; - - RtlEnterCriticalSection( &exclusive_datafile_list_section ); - LIST_FOR_EACH_ENTRY( file, &exclusive_datafile_list, struct exclusive_datafile, entry ) - { - if (file->module != module) continue; - TRACE( "closing %p for module %p\n", file->file, file->module ); - CloseHandle( file->file ); - list_remove( &file->entry ); - HeapFree( GetProcessHeap(), 0, file ); - break; - } - RtlLeaveCriticalSection( &exclusive_datafile_list_section ); - } - return UnmapViewOfFile( ptr ); - } - - return set_ntstatus( LdrUnloadDll( module )); -} - - -/*********************************************************************** - * GetModuleFileNameA (kernelbase.@) - */ -DWORD WINAPI DECLSPEC_HOTPATCH GetModuleFileNameA( HMODULE module, LPSTR filename, DWORD size ) -{ - LPWSTR filenameW = HeapAlloc( GetProcessHeap(), 0, size * sizeof(WCHAR) ); - DWORD len; - - if (!filenameW) - { - SetLastError( ERROR_NOT_ENOUGH_MEMORY ); - return 0; - } - if ((len = GetModuleFileNameW( module, filenameW, size ))) - { - len = file_name_WtoA( filenameW, len, filename, size ); - if (len < size) - filename[len] = 0; - else - SetLastError( ERROR_INSUFFICIENT_BUFFER ); - } - HeapFree( GetProcessHeap(), 0, filenameW ); - return len; -} - - -/*********************************************************************** - * GetModuleFileNameW (kernelbase.@) - */ -DWORD WINAPI DECLSPEC_HOTPATCH GetModuleFileNameW( HMODULE module, LPWSTR filename, DWORD size ) -{ - ULONG len = 0; - WIN16_SUBSYSTEM_TIB *win16_tib; - UNICODE_STRING name; - NTSTATUS status; - - if (!module && ((win16_tib = NtCurrentTeb()->Tib.SubSystemTib)) && win16_tib->exe_name) - { - len = min( size, win16_tib->exe_name->Length / sizeof(WCHAR) ); - memcpy( filename, win16_tib->exe_name->Buffer, len * sizeof(WCHAR) ); - if (len < size) filename[len] = 0; - goto done; - } - - name.Buffer = filename; - name.MaximumLength = min( size, UNICODE_STRING_MAX_CHARS ) * sizeof(WCHAR); - status = LdrGetDllFullName( module, &name ); - if (!status || status == STATUS_BUFFER_TOO_SMALL) len = name.Length / sizeof(WCHAR); - SetLastError( RtlNtStatusToDosError( status )); -done: - TRACE( "%s\n", debugstr_wn(filename, len) ); - return len; -} - - -/*********************************************************************** - * GetModuleHandleA (kernelbase.@) - */ -HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA( LPCSTR module ) -{ - HMODULE ret; - - GetModuleHandleExA( GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, module, &ret ); - return ret; -} - - -/*********************************************************************** - * GetModuleHandleW (kernelbase.@) - */ -HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleW( LPCWSTR module ) -{ - HMODULE ret; - - GetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, module, &ret ); - return ret; -} - - -/*********************************************************************** - * GetModuleHandleExA (kernelbase.@) - */ -BOOL WINAPI DECLSPEC_HOTPATCH GetModuleHandleExA( DWORD flags, LPCSTR name, HMODULE *module ) -{ - WCHAR *nameW; - - if (!module) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return FALSE; - } - - if (!name || (flags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS)) - return GetModuleHandleExW( flags, (LPCWSTR)name, module ); - - if (!(nameW = file_name_AtoW( name, FALSE ))) - { - *module = NULL; - SetLastError( ERROR_MOD_NOT_FOUND ); - return FALSE; - } - return GetModuleHandleExW( flags, nameW, module ); -} - - -/*********************************************************************** - * GetModuleHandleExW (kernelbase.@) - */ -BOOL WINAPI DECLSPEC_HOTPATCH GetModuleHandleExW( DWORD flags, LPCWSTR name, HMODULE *module ) -{ - HMODULE ret = NULL; - NTSTATUS status; - void *dummy; - - if (!module) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return FALSE; - } - - if ((flags & ~(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT - | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS)) - || (flags & (GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)) - == (GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)) - { - *module = NULL; - SetLastError( ERROR_INVALID_PARAMETER ); - return FALSE; - } - - if (name && !(flags & GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS)) - { - UNICODE_STRING wstr; - ULONG ldr_flags = 0; - - if (flags & GET_MODULE_HANDLE_EX_FLAG_PIN) - ldr_flags |= LDR_GET_DLL_HANDLE_EX_FLAG_PIN; - if (flags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT) - ldr_flags |= LDR_GET_DLL_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT; - - RtlInitUnicodeString( &wstr, name ); - status = LdrGetDllHandleEx( ldr_flags, NULL, NULL, &wstr, &ret ); - } - else - { - ret = name ? RtlPcToFileHeader( (void *)name, &dummy ) : NtCurrentTeb()->Peb->ImageBaseAddress; - - if (ret) - { - if (!(flags & GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT)) - status = LdrAddRefDll( flags & GET_MODULE_HANDLE_EX_FLAG_PIN ? LDR_ADDREF_DLL_PIN : 0, ret ); - else - status = STATUS_SUCCESS; - } else status = STATUS_DLL_NOT_FOUND; - } - - *module = ret; - return set_ntstatus( status ); -} - - -/*********************************************************************** - * GetProcAddress (kernelbase.@) - */ - -/* - * Work around a Delphi bug on x86_64. When delay loading a symbol, - * Delphi saves rcx, rdx, r8 and r9 to the stack. It then calls - * GetProcAddress(), pops the saved registers and calls the function. - * This works fine if all of the parameters are ints. However, since - * it does not save xmm0 - 3, it relies on GetProcAddress() preserving - * these registers if the function takes floating point parameters. - * This wrapper saves xmm0 - 3 to the stack. - */ -#ifdef __arm64ec__ -FARPROC WINAPI __attribute__((naked)) GetProcAddress( HMODULE module, LPCSTR function ) -{ - asm( ".seh_proc \"#GetProcAddress\"\n\t" - "stp x29, x30, [sp, #-48]!\n\t" - ".seh_save_fplr_x 48\n\t" - ".seh_endprologue\n\t" - "stp d0, d1, [sp, #16]\n\t" - "stp d2, d3, [sp, #32]\n\t" - "bl \"#get_proc_address\"\n\t" - "ldp d0, d1, [sp, #16]\n\t" - "ldp d2, d3, [sp, #32]\n\t" - "ldp x29, x30, [sp], #48\n\t" - "ret\n\t" - ".seh_endproc" ); -} -#elif defined(__x86_64__) -__ASM_GLOBAL_FUNC( GetProcAddress, - ".byte 0x48\n\t" /* hotpatch prolog */ - "pushq %rbp\n\t" - __ASM_SEH(".seh_pushreg %rbp\n\t") - __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t") - __ASM_CFI(".cfi_rel_offset %rbp,0\n\t") - "movq %rsp,%rbp\n\t" - __ASM_SEH(".seh_setframe %rbp,0\n\t") - __ASM_CFI(".cfi_def_cfa_register %rbp\n\t") - __ASM_SEH(".seh_endprologue\n\t") - "subq $0x60,%rsp\n\t" - "andq $~15,%rsp\n\t" - "movaps %xmm0,0x20(%rsp)\n\t" - "movaps %xmm1,0x30(%rsp)\n\t" - "movaps %xmm2,0x40(%rsp)\n\t" - "movaps %xmm3,0x50(%rsp)\n\t" - "call " __ASM_NAME("get_proc_address") "\n\t" - "movaps 0x50(%rsp), %xmm3\n\t" - "movaps 0x40(%rsp), %xmm2\n\t" - "movaps 0x30(%rsp), %xmm1\n\t" - "movaps 0x20(%rsp), %xmm0\n\t" - "leaq 0(%rbp),%rsp\n\t" - __ASM_CFI(".cfi_def_cfa_register %rsp\n\t") - "popq %rbp\n\t" - __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t") - __ASM_CFI(".cfi_same_value %rbp\n\t") - "ret" ) -#else /* __x86_64__ */ - -FARPROC WINAPI DECLSPEC_HOTPATCH GetProcAddress( HMODULE module, LPCSTR function ) -{ - return get_proc_address( module, function ); -} - -#endif /* __x86_64__ */ - - -/*********************************************************************** - * IsApiSetImplemented (kernelbase.@) - */ -BOOL WINAPI IsApiSetImplemented( LPCSTR name ) -{ - UNICODE_STRING str; - NTSTATUS status; - BOOLEAN in_schema, present; - - if (!RtlCreateUnicodeStringFromAsciiz( &str, name )) return FALSE; - status = ApiSetQueryApiSetPresenceEx( &str, &in_schema, &present ); - RtlFreeUnicodeString( &str ); - return !status && present; -} - - -/*********************************************************************** - * LoadLibraryA (kernelbase.@) - */ -HMODULE WINAPI DECLSPEC_HOTPATCH LoadLibraryA( LPCSTR name ) -{ - return LoadLibraryExA( name, 0, 0 ); -} - - -/*********************************************************************** - * LoadLibraryW (kernelbase.@) - */ -HMODULE WINAPI DECLSPEC_HOTPATCH LoadLibraryW( LPCWSTR name ) -{ - return LoadLibraryExW( name, 0, 0 ); -} - - -/****************************************************************** - * LoadLibraryExA (kernelbase.@) - */ -HMODULE WINAPI DECLSPEC_HOTPATCH LoadLibraryExA( LPCSTR name, HANDLE file, DWORD flags ) -{ - WCHAR *nameW; - HMODULE module; - - /* A new allocation is necessary due to TP Shell Service - * calling LoadLibraryExA from an LdrLoadDll hook */ - if (!(nameW = file_name_AtoW( name, TRUE ))) return 0; - - module = LoadLibraryExW( nameW, file, flags ); - - HeapFree( GetProcessHeap(), 0, nameW ); - return module; -} - - -/*********************************************************************** - * LoadLibraryExW (kernelbase.@) - */ -HMODULE WINAPI DECLSPEC_HOTPATCH LoadLibraryExW( LPCWSTR name, HANDLE file, DWORD flags ) -{ - UNICODE_STRING str; - HMODULE module; - - if (!name) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return 0; - } - RtlInitUnicodeString( &str, name ); - if (str.Length && str.Buffer[str.Length/sizeof(WCHAR) - 1] != ' ') return load_library( &str, flags ); - - /* library name has trailing spaces */ - RtlCreateUnicodeString( &str, name ); - while (str.Length > sizeof(WCHAR) && str.Buffer[str.Length/sizeof(WCHAR) - 1] == ' ') - str.Length -= sizeof(WCHAR); - - str.Buffer[str.Length/sizeof(WCHAR)] = 0; - module = load_library( &str, flags ); - RtlFreeUnicodeString( &str ); - return module; -} - - -/*********************************************************************** - * LoadPackagedLibrary (kernelbase.@) - */ -HMODULE WINAPI /* DECLSPEC_HOTPATCH */ LoadPackagedLibrary( LPCWSTR name, DWORD reserved ) -{ - FIXME( "semi-stub, name %s, reserved %#lx.\n", debugstr_w(name), reserved ); - SetLastError( APPMODEL_ERROR_NO_PACKAGE ); - return NULL; -} - - -/*********************************************************************** - * LoadAppInitDlls (kernelbase.@) - */ -void WINAPI LoadAppInitDlls(void) -{ - TRACE( "\n" ); -} - - -/**************************************************************************** - * RemoveDllDirectory (kernelbase.@) - */ -BOOL WINAPI DECLSPEC_HOTPATCH RemoveDllDirectory( DLL_DIRECTORY_COOKIE cookie ) -{ - return set_ntstatus( LdrRemoveDllDirectory( cookie )); -} - - -/************************************************************************* - * SetDefaultDllDirectories (kernelbase.@) - */ -BOOL WINAPI DECLSPEC_HOTPATCH SetDefaultDllDirectories( DWORD flags ) -{ - return set_ntstatus( LdrSetDefaultDllDirectories( flags )); -} - - -/*********************************************************************** - * Resources - ***********************************************************************/ - - -#define IS_INTRESOURCE(x) (((ULONG_PTR)(x) >> 16) == 0) - -/* retrieve the resource name to pass to the ntdll functions */ -static NTSTATUS get_res_nameA( LPCSTR name, UNICODE_STRING *str ) -{ - if (IS_INTRESOURCE(name)) - { - str->Buffer = ULongToPtr( LOWORD(name) ); - return STATUS_SUCCESS; - } - if (name[0] == '#') - { - ULONG value; - if (RtlCharToInteger( name + 1, 10, &value ) != STATUS_SUCCESS || HIWORD(value)) - return STATUS_INVALID_PARAMETER; - str->Buffer = ULongToPtr(value); - return STATUS_SUCCESS; - } - RtlCreateUnicodeStringFromAsciiz( str, name ); - RtlUpcaseUnicodeString( str, str, FALSE ); - return STATUS_SUCCESS; -} - -/* retrieve the resource name to pass to the ntdll functions */ -static NTSTATUS get_res_nameW( LPCWSTR name, UNICODE_STRING *str ) -{ - if (IS_INTRESOURCE(name)) - { - str->Buffer = ULongToPtr( LOWORD(name) ); - return STATUS_SUCCESS; - } - if (name[0] == '#') - { - ULONG value; - RtlInitUnicodeString( str, name + 1 ); - if (RtlUnicodeStringToInteger( str, 10, &value ) != STATUS_SUCCESS || HIWORD(value)) - return STATUS_INVALID_PARAMETER; - str->Buffer = ULongToPtr(value); - return STATUS_SUCCESS; - } - RtlCreateUnicodeString( str, name ); - RtlUpcaseUnicodeString( str, str, FALSE ); - return STATUS_SUCCESS; -} - - -/********************************************************************** - * EnumResourceLanguagesExA (kernelbase.@) - */ -BOOL WINAPI DECLSPEC_HOTPATCH EnumResourceLanguagesExA( HMODULE module, LPCSTR type, LPCSTR name, - ENUMRESLANGPROCA func, LONG_PTR param, - DWORD flags, LANGID lang ) -{ - int i; - BOOL ret = FALSE; - NTSTATUS status; - UNICODE_STRING typeW, nameW; - LDR_RESOURCE_INFO info; - const IMAGE_RESOURCE_DIRECTORY *basedir, *resdir; - const IMAGE_RESOURCE_DIRECTORY_ENTRY *et; - - TRACE( "%p %s %s %p %Ix %lx %d\n", module, debugstr_a(type), debugstr_a(name), - func, param, flags, lang ); - - if (flags & (RESOURCE_ENUM_MUI | RESOURCE_ENUM_MUI_SYSTEM | RESOURCE_ENUM_VALIDATE)) - FIXME( "unimplemented flags: %lx\n", flags ); - - if (!flags) flags = RESOURCE_ENUM_LN | RESOURCE_ENUM_MUI; - if (!(flags & RESOURCE_ENUM_LN)) return ret; - - if (!module) module = GetModuleHandleW( 0 ); - typeW.Buffer = nameW.Buffer = NULL; - if ((status = LdrFindResourceDirectory_U( module, NULL, 0, &basedir )) != STATUS_SUCCESS) - goto done; - if ((status = get_res_nameA( type, &typeW )) != STATUS_SUCCESS) - goto done; - if ((status = get_res_nameA( name, &nameW )) != STATUS_SUCCESS) - goto done; - info.Type = (ULONG_PTR)typeW.Buffer; - info.Name = (ULONG_PTR)nameW.Buffer; - if ((status = LdrFindResourceDirectory_U( module, &info, 2, &resdir )) != STATUS_SUCCESS) - goto done; - - et = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(resdir + 1); - __TRY - { - for (i = 0; i < resdir->NumberOfNamedEntries + resdir->NumberOfIdEntries; i++) - { - ret = func( module, type, name, et[i].Id, param ); - if (!ret) break; - } - } - __EXCEPT_PAGE_FAULT - { - ret = FALSE; - status = STATUS_ACCESS_VIOLATION; - } - __ENDTRY -done: - if (!IS_INTRESOURCE(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer ); - if (!IS_INTRESOURCE(nameW.Buffer)) HeapFree( GetProcessHeap(), 0, nameW.Buffer ); - if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) ); - return ret; -} - - -/********************************************************************** - * EnumResourceLanguagesExW (kernelbase.@) - */ -BOOL WINAPI DECLSPEC_HOTPATCH EnumResourceLanguagesExW( HMODULE module, LPCWSTR type, LPCWSTR name, - ENUMRESLANGPROCW func, LONG_PTR param, - DWORD flags, LANGID lang ) -{ - int i; - BOOL ret = FALSE; - NTSTATUS status; - UNICODE_STRING typeW, nameW; - LDR_RESOURCE_INFO info; - const IMAGE_RESOURCE_DIRECTORY *basedir, *resdir; - const IMAGE_RESOURCE_DIRECTORY_ENTRY *et; - - TRACE( "%p %s %s %p %Ix %lx %d\n", module, debugstr_w(type), debugstr_w(name), - func, param, flags, lang ); - - if (flags & (RESOURCE_ENUM_MUI | RESOURCE_ENUM_MUI_SYSTEM | RESOURCE_ENUM_VALIDATE)) - FIXME( "unimplemented flags: %lx\n", flags ); - - if (!flags) flags = RESOURCE_ENUM_LN | RESOURCE_ENUM_MUI; - if (!(flags & RESOURCE_ENUM_LN)) return ret; - - if (!module) module = GetModuleHandleW( 0 ); - typeW.Buffer = nameW.Buffer = NULL; - if ((status = LdrFindResourceDirectory_U( module, NULL, 0, &basedir )) != STATUS_SUCCESS) - goto done; - if ((status = get_res_nameW( type, &typeW )) != STATUS_SUCCESS) - goto done; - if ((status = get_res_nameW( name, &nameW )) != STATUS_SUCCESS) - goto done; - info.Type = (ULONG_PTR)typeW.Buffer; - info.Name = (ULONG_PTR)nameW.Buffer; - if ((status = LdrFindResourceDirectory_U( module, &info, 2, &resdir )) != STATUS_SUCCESS) - goto done; - - et = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(resdir + 1); - __TRY - { - for (i = 0; i < resdir->NumberOfNamedEntries + resdir->NumberOfIdEntries; i++) - { - ret = func( module, type, name, et[i].Id, param ); - if (!ret) break; - } - } - __EXCEPT_PAGE_FAULT - { - ret = FALSE; - status = STATUS_ACCESS_VIOLATION; - } - __ENDTRY -done: - if (!IS_INTRESOURCE(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer ); - if (!IS_INTRESOURCE(nameW.Buffer)) HeapFree( GetProcessHeap(), 0, nameW.Buffer ); - if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) ); - return ret; -} - - -/********************************************************************** - * EnumResourceNamesExA (kernelbase.@) - */ -BOOL WINAPI DECLSPEC_HOTPATCH EnumResourceNamesExA( HMODULE module, LPCSTR type, ENUMRESNAMEPROCA func, - LONG_PTR param, DWORD flags, LANGID lang ) -{ - int i; - BOOL ret = FALSE; - DWORD len = 0, newlen; - LPSTR name = NULL; - NTSTATUS status; - UNICODE_STRING typeW; - LDR_RESOURCE_INFO info; - const IMAGE_RESOURCE_DIRECTORY *basedir, *resdir; - const IMAGE_RESOURCE_DIRECTORY_ENTRY *et; - const IMAGE_RESOURCE_DIR_STRING_U *str; - - TRACE( "%p %s %p %Ix\n", module, debugstr_a(type), func, param ); - - if (flags & (RESOURCE_ENUM_MUI | RESOURCE_ENUM_MUI_SYSTEM | RESOURCE_ENUM_VALIDATE)) - FIXME( "unimplemented flags: %lx\n", flags ); - - if (!flags) flags = RESOURCE_ENUM_LN | RESOURCE_ENUM_MUI; - if (!(flags & RESOURCE_ENUM_LN)) return ret; - - if (!module) module = GetModuleHandleW( 0 ); - typeW.Buffer = NULL; - if ((status = LdrFindResourceDirectory_U( module, NULL, 0, &basedir )) != STATUS_SUCCESS) - goto done; - if ((status = get_res_nameA( type, &typeW )) != STATUS_SUCCESS) - goto done; - info.Type = (ULONG_PTR)typeW.Buffer; - if ((status = LdrFindResourceDirectory_U( module, &info, 1, &resdir )) != STATUS_SUCCESS) - goto done; - - et = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(resdir + 1); - __TRY - { - for (i = 0; i < resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries; i++) - { - if (et[i].NameIsString) - { - str = (const IMAGE_RESOURCE_DIR_STRING_U *)((const BYTE *)basedir + et[i].NameOffset); - newlen = WideCharToMultiByte(CP_ACP, 0, str->NameString, str->Length, NULL, 0, NULL, NULL); - if (newlen + 1 > len) - { - len = newlen + 1; - HeapFree( GetProcessHeap(), 0, name ); - if (!(name = HeapAlloc( GetProcessHeap(), 0, len + 1 ))) - { - ret = FALSE; - break; - } - } - WideCharToMultiByte( CP_ACP, 0, str->NameString, str->Length, name, len, NULL, NULL ); - name[newlen] = 0; - ret = func( module, type, name, param ); - } - else - { - ret = func( module, type, UIntToPtr(et[i].Id), param ); - } - if (!ret) break; - } - } - __EXCEPT_PAGE_FAULT - { - ret = FALSE; - status = STATUS_ACCESS_VIOLATION; - } - __ENDTRY - -done: - HeapFree( GetProcessHeap(), 0, name ); - if (!IS_INTRESOURCE(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer ); - if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) ); - return ret; -} - - -/********************************************************************** - * EnumResourceNamesExW (kernelbase.@) - */ -BOOL WINAPI DECLSPEC_HOTPATCH EnumResourceNamesExW( HMODULE module, LPCWSTR type, ENUMRESNAMEPROCW func, - LONG_PTR param, DWORD flags, LANGID lang ) -{ - int i, len = 0; - BOOL ret = FALSE; - LPWSTR name = NULL; - NTSTATUS status; - UNICODE_STRING typeW; - LDR_RESOURCE_INFO info; - const IMAGE_RESOURCE_DIRECTORY *basedir, *resdir; - const IMAGE_RESOURCE_DIRECTORY_ENTRY *et; - const IMAGE_RESOURCE_DIR_STRING_U *str; - - TRACE( "%p %s %p %Ix\n", module, debugstr_w(type), func, param ); - - if (flags & (RESOURCE_ENUM_MUI | RESOURCE_ENUM_MUI_SYSTEM | RESOURCE_ENUM_VALIDATE)) - FIXME( "unimplemented flags: %lx\n", flags ); - - if (!flags) flags = RESOURCE_ENUM_LN | RESOURCE_ENUM_MUI; - if (!(flags & RESOURCE_ENUM_LN)) return ret; - - if (!module) module = GetModuleHandleW( 0 ); - typeW.Buffer = NULL; - if ((status = LdrFindResourceDirectory_U( module, NULL, 0, &basedir )) != STATUS_SUCCESS) - goto done; - if ((status = get_res_nameW( type, &typeW )) != STATUS_SUCCESS) - goto done; - info.Type = (ULONG_PTR)typeW.Buffer; - if ((status = LdrFindResourceDirectory_U( module, &info, 1, &resdir )) != STATUS_SUCCESS) - goto done; - - et = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(resdir + 1); - __TRY - { - for (i = 0; i < resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries; i++) - { - if (et[i].NameIsString) - { - str = (const IMAGE_RESOURCE_DIR_STRING_U *)((const BYTE *)basedir + et[i].NameOffset); - if (str->Length + 1 > len) - { - len = str->Length + 1; - HeapFree( GetProcessHeap(), 0, name ); - if (!(name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) - { - ret = FALSE; - break; - } - } - memcpy(name, str->NameString, str->Length * sizeof (WCHAR)); - name[str->Length] = 0; - ret = func( module, type, name, param ); - } - else - { - ret = func( module, type, UIntToPtr(et[i].Id), param ); - } - if (!ret) break; - } - } - __EXCEPT_PAGE_FAULT - { - ret = FALSE; - status = STATUS_ACCESS_VIOLATION; - } - __ENDTRY -done: - HeapFree( GetProcessHeap(), 0, name ); - if (!IS_INTRESOURCE(typeW.Buffer)) HeapFree( GetProcessHeap(), 0, typeW.Buffer ); - if (status != STATUS_SUCCESS) SetLastError( RtlNtStatusToDosError(status) ); - return ret; -} - - -/********************************************************************** - * EnumResourceNamesW (kernelbase.@) - */ -BOOL WINAPI DECLSPEC_HOTPATCH EnumResourceNamesW( HMODULE module, LPCWSTR type, - ENUMRESNAMEPROCW func, LONG_PTR param ) -{ - return EnumResourceNamesExW( module, type, func, param, 0, 0 ); -} - - -/********************************************************************** - * EnumResourceTypesExA (kernelbase.@) - */ -BOOL WINAPI DECLSPEC_HOTPATCH EnumResourceTypesExA( HMODULE module, ENUMRESTYPEPROCA func, LONG_PTR param, - DWORD flags, LANGID lang ) -{ - int i; - BOOL ret = FALSE; - LPSTR type = NULL; - DWORD len = 0, newlen; - const IMAGE_RESOURCE_DIRECTORY *resdir; - const IMAGE_RESOURCE_DIRECTORY_ENTRY *et; - const IMAGE_RESOURCE_DIR_STRING_U *str; - - TRACE( "%p %p %Ix\n", module, func, param ); - - if (flags & (RESOURCE_ENUM_MUI | RESOURCE_ENUM_MUI_SYSTEM | RESOURCE_ENUM_VALIDATE)) - FIXME( "unimplemented flags: %lx\n", flags ); - - if (!flags) flags = RESOURCE_ENUM_LN | RESOURCE_ENUM_MUI; - if (!(flags & RESOURCE_ENUM_LN)) return ret; - - if (!module) module = GetModuleHandleW( 0 ); - - if (!set_ntstatus( LdrFindResourceDirectory_U( module, NULL, 0, &resdir ))) return FALSE; - - et = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(resdir + 1); - for (i = 0; i < resdir->NumberOfNamedEntries+resdir->NumberOfIdEntries; i++) - { - if (et[i].NameIsString) - { - str = (const IMAGE_RESOURCE_DIR_STRING_U *)((const BYTE *)resdir + et[i].NameOffset); - newlen = WideCharToMultiByte( CP_ACP, 0, str->NameString, str->Length, NULL, 0, NULL, NULL); - if (newlen + 1 > len) - { - len = newlen + 1; - HeapFree( GetProcessHeap(), 0, type ); - if (!(type = HeapAlloc( GetProcessHeap(), 0, len ))) return FALSE; - } - WideCharToMultiByte( CP_ACP, 0, str->NameString, str->Length, type, len, NULL, NULL); - type[newlen] = 0; - ret = func( module, type, param ); - } - else - { - ret = func( module, UIntToPtr(et[i].Id), param ); - } - if (!ret) break; - } - HeapFree( GetProcessHeap(), 0, type ); - return ret; -} - - -/********************************************************************** - * EnumResourceTypesExW (kernelbase.@) - */ -BOOL WINAPI DECLSPEC_HOTPATCH EnumResourceTypesExW( HMODULE module, ENUMRESTYPEPROCW func, LONG_PTR param, - DWORD flags, LANGID lang ) -{ - int i, len = 0; - BOOL ret = FALSE; - LPWSTR type = NULL; - const IMAGE_RESOURCE_DIRECTORY *resdir; - const IMAGE_RESOURCE_DIRECTORY_ENTRY *et; - const IMAGE_RESOURCE_DIR_STRING_U *str; - - TRACE( "%p %p %Ix\n", module, func, param ); - - if (!flags) flags = RESOURCE_ENUM_LN | RESOURCE_ENUM_MUI; - if (!(flags & RESOURCE_ENUM_LN)) return ret; - - if (!module) module = GetModuleHandleW( 0 ); - - if (!set_ntstatus( LdrFindResourceDirectory_U( module, NULL, 0, &resdir ))) return FALSE; - - et = (const IMAGE_RESOURCE_DIRECTORY_ENTRY *)(resdir + 1); - for (i = 0; i < resdir->NumberOfNamedEntries + resdir->NumberOfIdEntries; i++) - { - if (et[i].NameIsString) - { - str = (const IMAGE_RESOURCE_DIR_STRING_U *)((const BYTE *)resdir + et[i].NameOffset); - if (str->Length + 1 > len) - { - len = str->Length + 1; - HeapFree( GetProcessHeap(), 0, type ); - if (!(type = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return FALSE; - } - memcpy(type, str->NameString, str->Length * sizeof (WCHAR)); - type[str->Length] = 0; - ret = func( module, type, param ); - } - else - { - ret = func( module, UIntToPtr(et[i].Id), param ); - } - if (!ret) break; - } - HeapFree( GetProcessHeap(), 0, type ); - return ret; -} - - -/***********************************************************************/ -/* get_mui - Acquire an MUI module for the associated resource */ -/***********************************************************************/ - -HMODULE get_mui(HMODULE module) -{ - WCHAR module_name[MAX_PATH], mui_name[MAX_PATH]; - HMODULE mui_module = NULL; - INT i, j = 0, k = 0, l = 0; - - /* Initialize the work strings */ - - for (i = 0; i < MAX_PATH; i++) { - module_name[i] = 0; - mui_name[i] = 0; - } - - /* Acquire the base resource file name */ - - 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; - - 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. */ - - 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. */ - - 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 != 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; - LDR_RESOURCE_INFO info; - const IMAGE_RESOURCE_DATA_ENTRY *entry = NULL; - - TRACE( "%p %s %s %04x\n", module, debugstr_w(type), debugstr_w(name), lang ); - - nameW.Buffer = typeW.Buffer = NULL; - - __TRY - { - if ((status = get_res_nameW( name, &nameW )) != STATUS_SUCCESS) goto done; - 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; - status = LdrFindResource_U( module, &info, 3, &entry ); - done: - if (status != STATUS_SUCCESS) - SetLastError( RtlNtStatusToDosError(status) ); - } - __EXCEPT_PAGE_FAULT - { - SetLastError( ERROR_INVALID_PARAMETER ); - } - __ENDTRY - - 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); - - /* 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); - module_mui = NULL; - } - } - } - - return rsrc; - -} - -/********************************************************************** - * FindResourceW (kernelbase.@) - */ -HRSRC WINAPI DECLSPEC_HOTPATCH FindResourceW( HINSTANCE module, LPCWSTR name, LPCWSTR type ) -{ - return FindResourceExW( module, type, name, MAKELANGID( LANG_NEUTRAL, SUBLANG_NEUTRAL ) ); -} - - -/********************************************************************** - * FreeResource (kernelbase.@) - */ -BOOL WINAPI DECLSPEC_HOTPATCH FreeResource( HGLOBAL handle ) -{ - return FALSE; -} - - -/********************************************************************** - * LoadResource (kernelbase.@) - */ -HGLOBAL WINAPI DECLSPEC_HOTPATCH LoadResource( HINSTANCE module, HRSRC rsrc ) -{ - void *ret; - HMODULE work_module = NULL; - - if (!rsrc) return 0; - if (!module) module = GetModuleHandleW( 0 ); - 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; - -} - - -/********************************************************************** - * LockResource (kernelbase.@) - */ -LPVOID WINAPI DECLSPEC_HOTPATCH LockResource( HGLOBAL handle ) -{ - return handle; -} - - -/********************************************************************** - * SizeofResource (kernelbase.@) - */ -DWORD WINAPI DECLSPEC_HOTPATCH SizeofResource( HINSTANCE module, HRSRC rsrc ) -{ - if (!rsrc) return 0; - return ((IMAGE_RESOURCE_DATA_ENTRY *)rsrc)->Size; -} - - -/*********************************************************************** - * Activation contexts - ***********************************************************************/ - - -/*********************************************************************** - * ActivateActCtx (kernelbase.@) - */ -BOOL WINAPI DECLSPEC_HOTPATCH ActivateActCtx( HANDLE context, ULONG_PTR *cookie ) -{ - return set_ntstatus( RtlActivateActivationContext( 0, context, cookie )); -} - - -/*********************************************************************** - * AddRefActCtx (kernelbase.@) - */ -void WINAPI DECLSPEC_HOTPATCH AddRefActCtx( HANDLE context ) -{ - RtlAddRefActivationContext( context ); -} - - -/*********************************************************************** - * CreateActCtxW (kernelbase.@) - */ -HANDLE WINAPI DECLSPEC_HOTPATCH CreateActCtxW( PCACTCTXW ctx ) -{ - struct _ACTIVATION_CONTEXT *context; - - TRACE( "%p %08lx\n", ctx, ctx ? ctx->dwFlags : 0 ); - - if (!set_ntstatus( RtlCreateActivationContext( &context, ctx ))) return INVALID_HANDLE_VALUE; - return context; -} - - -/*********************************************************************** - * DeactivateActCtx (kernelbase.@) - */ -BOOL WINAPI DECLSPEC_HOTPATCH DeactivateActCtx( DWORD flags, ULONG_PTR cookie ) -{ - RtlDeactivateActivationContext( flags, cookie ); - return TRUE; -} - - -/*********************************************************************** - * FindActCtxSectionGuid (kernelbase.@) - */ -BOOL WINAPI DECLSPEC_HOTPATCH FindActCtxSectionGuid( DWORD flags, const GUID *ext_guid, ULONG id, - const GUID *guid, PACTCTX_SECTION_KEYED_DATA info ) -{ - return set_ntstatus( RtlFindActivationContextSectionGuid( flags, ext_guid, id, guid, info )); -} - - -/*********************************************************************** - * FindActCtxSectionStringW (kernelbase.@) - */ -BOOL WINAPI DECLSPEC_HOTPATCH FindActCtxSectionStringW( DWORD flags, const GUID *ext_guid, ULONG id, - LPCWSTR str, PACTCTX_SECTION_KEYED_DATA info ) -{ - UNICODE_STRING us; - - if (!info) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return FALSE; - } - RtlInitUnicodeString( &us, str ); - return set_ntstatus( RtlFindActivationContextSectionString( flags, ext_guid, id, &us, info )); -} - - -/*********************************************************************** - * GetCurrentActCtx (kernelbase.@) - */ -BOOL WINAPI DECLSPEC_HOTPATCH GetCurrentActCtx( HANDLE *pcontext ) -{ - return set_ntstatus( RtlGetActiveActivationContext( (struct _ACTIVATION_CONTEXT **)pcontext )); -} - - -/*********************************************************************** - * QueryActCtxSettingsW (kernelbase.@) - */ -BOOL WINAPI DECLSPEC_HOTPATCH QueryActCtxSettingsW( DWORD flags, HANDLE ctx, const WCHAR *ns, - const WCHAR *settings, WCHAR *buffer, SIZE_T size, - SIZE_T *written ) -{ - return set_ntstatus( RtlQueryActivationContextApplicationSettings( flags, ctx, ns, settings, - buffer, size, written )); -} - - -/*********************************************************************** - * QueryActCtxW (kernelbase.@) - */ -BOOL WINAPI DECLSPEC_HOTPATCH QueryActCtxW( DWORD flags, HANDLE context, PVOID inst, ULONG class, - PVOID buffer, SIZE_T size, SIZE_T *written ) -{ - return set_ntstatus( RtlQueryInformationActivationContext( flags, context, inst, class, - buffer, size, written )); -} - - -/*********************************************************************** - * ReleaseActCtx (kernelbase.@) - */ -void WINAPI DECLSPEC_HOTPATCH ReleaseActCtx( HANDLE context ) -{ - RtlReleaseActivationContext( context ); -} - - -/*********************************************************************** - * ZombifyActCtx (kernelbase.@) - */ -BOOL WINAPI DECLSPEC_HOTPATCH ZombifyActCtx( HANDLE context ) -{ - return set_ntstatus( RtlZombifyActivationContext( context )); -} -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10209
participants (2)
-
Craig Schulstad -
Craig Schulstad (@NoDakker)