Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com --- dlls/kernel32/tests/Makefile.in | 10 +- dlls/kernel32/tests/forward1.c | 17 +++ dlls/kernel32/tests/forward1.spec | 2 + dlls/kernel32/tests/forward2.c | 7 ++ dlls/kernel32/tests/forward2.spec | 2 + dlls/kernel32/tests/forward3.c | 7 ++ dlls/kernel32/tests/forward3.spec | 2 + dlls/kernel32/tests/forward4.c | 41 ++++++ dlls/kernel32/tests/forward4.spec | 2 + dlls/kernel32/tests/iatgas.h | 85 +++++++++++++ dlls/kernel32/tests/loader.c | 199 ++++++++++++++++++++++++++++++ 11 files changed, 373 insertions(+), 1 deletion(-) create mode 100644 dlls/kernel32/tests/forward1.c create mode 100644 dlls/kernel32/tests/forward1.spec create mode 100644 dlls/kernel32/tests/forward2.c create mode 100644 dlls/kernel32/tests/forward2.spec create mode 100644 dlls/kernel32/tests/forward3.c create mode 100644 dlls/kernel32/tests/forward3.spec create mode 100644 dlls/kernel32/tests/forward4.c create mode 100644 dlls/kernel32/tests/forward4.spec create mode 100644 dlls/kernel32/tests/iatgas.h
diff --git a/dlls/kernel32/tests/Makefile.in b/dlls/kernel32/tests/Makefile.in index e9516603ce9..7ef3508bad4 100644 --- a/dlls/kernel32/tests/Makefile.in +++ b/dlls/kernel32/tests/Makefile.in @@ -37,4 +37,12 @@ SOURCES = \ toolhelp.c \ version.c \ virtual.c \ - volume.c + volume.c \ + forward1.c \ + forward1.spec \ + forward2.c \ + forward2.spec \ + forward3.c \ + forward3.spec \ + forward4.c \ + forward4.spec diff --git a/dlls/kernel32/tests/forward1.c b/dlls/kernel32/tests/forward1.c new file mode 100644 index 00000000000..985e193c958 --- /dev/null +++ b/dlls/kernel32/tests/forward1.c @@ -0,0 +1,17 @@ +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +BOOL WINAPI DllMain(HINSTANCE instance_new, DWORD reason, LPVOID reserved) +{ + return TRUE; +} + +unsigned long forward_test_func(void) +{ + return 0x00005678UL; +} + +unsigned long forward_test_func2(void) +{ + return 0x12340000UL; +} diff --git a/dlls/kernel32/tests/forward1.spec b/dlls/kernel32/tests/forward1.spec new file mode 100644 index 00000000000..bf19fa7e011 --- /dev/null +++ b/dlls/kernel32/tests/forward1.spec @@ -0,0 +1,2 @@ +1 cdecl forward_test_func() +2 cdecl -noname forward_test_func2() diff --git a/dlls/kernel32/tests/forward2.c b/dlls/kernel32/tests/forward2.c new file mode 100644 index 00000000000..0ed3885e0df --- /dev/null +++ b/dlls/kernel32/tests/forward2.c @@ -0,0 +1,7 @@ +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +BOOL WINAPI DllMain(HINSTANCE instance_new, DWORD reason, LPVOID reserved) +{ + return TRUE; +} diff --git a/dlls/kernel32/tests/forward2.spec b/dlls/kernel32/tests/forward2.spec new file mode 100644 index 00000000000..374156d8d06 --- /dev/null +++ b/dlls/kernel32/tests/forward2.spec @@ -0,0 +1,2 @@ +1 cdecl forward_test_func() forward1.forward_test_func +2 cdecl -noname forward_test_func2() forward1.#2 diff --git a/dlls/kernel32/tests/forward3.c b/dlls/kernel32/tests/forward3.c new file mode 100644 index 00000000000..0ed3885e0df --- /dev/null +++ b/dlls/kernel32/tests/forward3.c @@ -0,0 +1,7 @@ +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +BOOL WINAPI DllMain(HINSTANCE instance_new, DWORD reason, LPVOID reserved) +{ + return TRUE; +} diff --git a/dlls/kernel32/tests/forward3.spec b/dlls/kernel32/tests/forward3.spec new file mode 100644 index 00000000000..31d019aa071 --- /dev/null +++ b/dlls/kernel32/tests/forward3.spec @@ -0,0 +1,2 @@ +1 cdecl forward_test_func() forward2.forward_test_func +2 cdecl -noname forward_test_func2() forward2.#2 diff --git a/dlls/kernel32/tests/forward4.c b/dlls/kernel32/tests/forward4.c new file mode 100644 index 00000000000..df4cfe41c0c --- /dev/null +++ b/dlls/kernel32/tests/forward4.c @@ -0,0 +1,41 @@ +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#if (defined(_MSC_VER) && defined(__clang__)) || defined(__MINGW32__) || defined(__CYGWIN__) +#include "wine/asm.h" +#include "iatgas.h" + +INLINE_IMPORT_BEGIN("forward3.dll") + INLINE_IMPORT_BY_NAME(1, "forward_test_func", __ASM_NAME("forward_test_func")) + INLINE_IMPORT_BY_ORDINAL(2, __ASM_NAME("forward_test_func2")) +INLINE_IMPORT_END() + +DECLSPEC_IMPORT extern unsigned long forward_test_func(void); +DECLSPEC_IMPORT extern unsigned long forward_test_func2(void); + +unsigned long test_func_stub(void) +{ + return forward_test_func() ^ forward_test_func2(); +} + +const char skiptest[] = ""; +#else +unsigned long test_func_stub(void) +{ + /* unimplemented */ + for (;;) DebugBreak(); +} + +#ifdef _MSC_VER +const char skiptest[] = "TODO: support building import libraries for TESTDLLs in MSVC"; +#elif defined(__WINE_PE_BUILD) +const char skiptest[] = "TODO: support building import libraries for TESTDLLs in other compilers"; +#else +const char skiptest[] = "TODO: support building import libraries for TESTDLLs as Unixlib (--without-mingw)"; +#endif +#endif + +BOOL WINAPI DllMain(HINSTANCE instance_new, DWORD reason, LPVOID reserved) +{ + return TRUE; +} diff --git a/dlls/kernel32/tests/forward4.spec b/dlls/kernel32/tests/forward4.spec new file mode 100644 index 00000000000..5ff2f47469c --- /dev/null +++ b/dlls/kernel32/tests/forward4.spec @@ -0,0 +1,2 @@ +@ cdecl test_func_stub() +@ extern skiptest diff --git a/dlls/kernel32/tests/iatgas.h b/dlls/kernel32/tests/iatgas.h new file mode 100644 index 00000000000..8d0184c9ae0 --- /dev/null +++ b/dlls/kernel32/tests/iatgas.h @@ -0,0 +1,85 @@ +/* + * Inline assembly import library generator + * + * Copyright 2021 Jinoh Kang + * + * 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 + */ + +#ifndef __WINE_KERNEL_IATGAS_H +#define __WINE_KERNEL_IATGAS_H + +#if defined(_WIN64) +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define IATGAS_ZERO_EXTEND_32_TO_PTR(line) line "\n\t.skip 4" +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define IATGAS_ZERO_EXTEND_32_TO_PTR(line) ".skip 4\n\t" line +#else +#error unknown byte order +#endif +#define IATGAS_EMIT_PTRALIGN ".p2align 3" +#define IATGAS_EMIT_IMPORT_BY_ORDINAL(ordinal) ".quad (1<<63)|(" #ordinal ")" +#elif defined(_WIN32) +#define IATGAS_ZERO_EXTEND_32_TO_PTR(line) line +#define IATGAS_EMIT_PTRALIGN ".p2align 2" +#define IATGAS_EMIT_IMPORT_BY_ORDINAL(ordinal) ".long (1<<31)|(" #ordinal ")" +#else +#error unknown pointer size +#endif + +#define INLINE_IMPORT_BEGIN_PROLOG(id) INLINE_IMPORT_BEGIN_PROLOG_(id) +#define INLINE_IMPORT_BEGIN_PROLOG_(id) \ + __asm__( \ + ".section ".idata$2", "a"\n\t" /* IMAGE_IMPORT_DESCRIPTOR */ \ + ".rva .Limport_ilt_" #id "\n\t" /* .OriginalFirstThunk */ \ + ".long 0\n\t" /* .TimeDateStamp */ \ + ".long -1\n\t" /* .ForwarderChain */ \ + ".rva .Limport_dllname_" #id "\n\t" /* .Name */ \ + ".rva .Limport_iat_" #id "\n\t" /* .FirstThunk */ \ + ".p2align 2\n\t" /* (section alignment) */ \ + ".section ".idata$4", "a"\n\t" /* IMAGE_THUNK_DATA (ILT) */ \ + IATGAS_EMIT_PTRALIGN "\n\t" \ + ".Limport_ilt_" #id ":\n\t" \ + ".section ".idata$5", "a"\n\t" /* IMAGE_THUNK_DATA (IAT) */ \ + IATGAS_EMIT_PTRALIGN "\n\t" \ + ".Limport_iat_" #id ":\n\t" \ + ".section ".idata$7", "a"\n\t" \ + ".Limport_dllname_" #id ":\n\t" +#define INLINE_IMPORT_BEGIN(dll_name) INLINE_IMPORT_BEGIN_PROLOG(__COUNTER__) \ + ".asciz "" dll_name ""\n\t" +#define INLINE_IMPORT_ENTRY(entry, impsym) \ + ".section ".idata$4", "a"\n\t" /* IMAGE_THUNK_DATA (ILT) */ \ + entry "\n\t" /* .AddressOfData | .Ordinal */ \ + ".section ".idata$5", "a"\n\t" \ + "__imp_" impsym ":\n\t" /* IMAGE_THUNK_DATA (IAT) */ \ + entry "\n\t" /* .AddressOfData | .Ordinal */ +#define INLINE_IMPORT_BY_ORDINAL(ordinal, impsym) \ + INLINE_IMPORT_ENTRY(IATGAS_EMIT_IMPORT_BY_ORDINAL(ordinal), impsym) +#define INLINE_IMPORT_BY_NAME(hint, name, impsym) \ + INLINE_IMPORT_ENTRY(IATGAS_ZERO_EXTEND_32_TO_PTR(".rva .Limport_procname_" impsym), impsym) \ + ".section ".idata$6", "a"\n\t" \ + ".Limport_procname_" impsym ":\n\t" /* IMAGE_IMPORT_BY_NAME */ \ + ".short " #hint "\n\t" /* .Hint */ \ + ".asciz "" name ""\n\t" /* .Name */ \ + ".p2align 1\n\t" /* (section alignment) */ +#define INLINE_IMPORT_END() \ + ".section ".idata$4", "a"\n\t" /* IMAGE_THUNK_DATA (ILT) */ \ + IATGAS_ZERO_EXTEND_32_TO_PTR(".long 0") "\n\t" \ + ".section ".idata$5", "a"\n\t" /* IMAGE_THUNK_DATA (IAT) */ \ + IATGAS_ZERO_EXTEND_32_TO_PTR(".long 0") "\n\t" \ + ".text" \ + ); + +#endif diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c index f990d632f73..97957604aa0 100644 --- a/dlls/kernel32/tests/loader.c +++ b/dlls/kernel32/tests/loader.c @@ -1642,6 +1642,202 @@ static void test_ImportDescriptors(void) } }
+static void extract_resource(const char *name, const char *type, const char *path) +{ + DWORD written; + HANDLE file; + HRSRC res; + void *ptr; + + file = CreateFileA(path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); + ok(file != INVALID_HANDLE_VALUE, "file creation failed, at %s, error %d\n", path, GetLastError()); + + res = FindResourceA(NULL, name, type); + ok( res != 0, "couldn't find resource\n" ); + ptr = LockResource( LoadResource( GetModuleHandleA(NULL), res )); + WriteFile( file, ptr, SizeofResource( GetModuleHandleA(NULL), res ), &written, NULL ); + ok( written == SizeofResource( GetModuleHandleA(NULL), res ), "couldn't write resource\n" ); + CloseHandle( file ); +} + +static void test_static_forwarded_import_refs(void) +{ + CHAR temp_path[MAX_PATH], dir_path[MAX_PATH]; + CHAR forward1_path[MAX_PATH]; + CHAR forward2_path[MAX_PATH]; + CHAR forward3_path[MAX_PATH]; + CHAR forward4_path[MAX_PATH]; + HMODULE forward1, forward2, forward3, forward4; + unsigned long result; + unsigned long (*test_func_stub)(void); + const char *skiptest; + BOOL skiptest_flag = FALSE; + + GetTempPathA( ARRAY_SIZE(temp_path), temp_path ); + GetTempFileNameA( temp_path, "ldr", GetTickCount() | 1UL, dir_path ); + ok( CreateDirectoryA( dir_path, NULL ), "failed to create dir %s, error %u\n", + dir_path, GetLastError() ); + + snprintf( forward1_path, MAX_PATH, "%s\forward1.dll", dir_path ); + snprintf( forward2_path, MAX_PATH, "%s\forward2.dll", dir_path ); + snprintf( forward3_path, MAX_PATH, "%s\forward3.dll", dir_path ); + snprintf( forward4_path, MAX_PATH, "%s\forward4.dll", dir_path ); + extract_resource( "forward1.dll", "TESTDLL", forward1_path ); + extract_resource( "forward2.dll", "TESTDLL", forward2_path ); + extract_resource( "forward3.dll", "TESTDLL", forward3_path ); + extract_resource( "forward4.dll", "TESTDLL", forward4_path ); + + forward1 = LoadLibraryA( forward1_path ); + ok( !!forward1, "couldn't find %s: %u\n", forward1_path, GetLastError() ); + forward2 = LoadLibraryA( forward2_path ); + ok( !!forward2, "couldn't find %s: %u\n", forward2_path, GetLastError() ); + forward3 = LoadLibraryA( forward3_path ); + ok( !!forward3, "couldn't find %s: %u\n", forward3_path, GetLastError() ); + forward4 = LoadLibraryA( forward4_path ); + ok( !!forward4, "couldn't find %s: %u\n", forward4_path, GetLastError() ); + + skiptest = (const char *)GetProcAddress( forward4, "skiptest" ); + if (skiptest && *skiptest) + { + skiptest_flag = TRUE; + skip( "forward4: %s\n", skiptest ); + } + else + { + test_func_stub = (void *)GetProcAddress( forward4, "test_func_stub" ); + ok( !!test_func_stub, "forward4!test_func_stub not found\n" ); + result = test_func_stub ? test_func_stub() : -1UL; + ok( result == 0x12345678UL, "forward4!test_func_stub returned %#lx (expected %#lx)\n", + result, 0x12345678UL ); + } + + FreeLibrary( forward1 ); + FreeLibrary( forward2 ); + FreeLibrary( forward3 ); + + if (!skiptest_flag) + { + todo_wine + ok( !!GetModuleHandleA( "forward1.dll" ), "forward1.dll unexpectedly unloaded\n" ); + todo_wine + ok( !!GetModuleHandleA( "forward2.dll" ), "forward2.dll unexpectedly unloaded\n" ); + ok( !!GetModuleHandleA( "forward3.dll" ), "forward3.dll unexpectedly unloaded\n" ); + } + + FreeLibrary( forward4 ); + + ok( !GetModuleHandleA( "forward1.dll" ), "forward1.dll unexpectedly kept open\n" ); + ok( !GetModuleHandleA( "forward2.dll" ), "forward2.dll unexpectedly kept open\n" ); + ok( !GetModuleHandleA( "forward3.dll" ), "forward3.dll unexpectedly kept open\n" ); + ok( !GetModuleHandleA( "forward4.dll" ), "forward4.dll unexpectedly kept open\n" ); + + DeleteFileA( forward1_path ); + DeleteFileA( forward2_path ); + DeleteFileA( forward3_path ); + DeleteFileA( forward4_path ); + RemoveDirectoryA( dir_path ); +} + +static void test_dynamic_forwarded_import_refs(void) +{ + CHAR temp_path[MAX_PATH], dir_path[MAX_PATH]; + CHAR forward1_path[MAX_PATH]; + CHAR forward2_path[MAX_PATH]; + CHAR forward3_path[MAX_PATH]; + HMODULE forward1, forward2, forward3; + FARPROC proc1, proc2, proc3; + + GetTempPathA( ARRAY_SIZE(temp_path), temp_path ); + GetTempFileNameA( temp_path, "ldr", GetTickCount() | 1UL, dir_path ); + ok( CreateDirectoryA( dir_path, NULL ), "failed to create dir %s, error %u\n", + dir_path, GetLastError() ); + + snprintf( forward1_path, MAX_PATH, "%s\forward1.dll", dir_path ); + snprintf( forward2_path, MAX_PATH, "%s\forward2.dll", dir_path ); + snprintf( forward3_path, MAX_PATH, "%s\forward3.dll", dir_path ); + extract_resource( "forward1.dll", "TESTDLL", forward1_path ); + extract_resource( "forward2.dll", "TESTDLL", forward2_path ); + extract_resource( "forward3.dll", "TESTDLL", forward3_path ); + + forward1 = LoadLibraryA( forward1_path ); + ok( !!forward1, "couldn't find %s: %u\n", forward1_path, GetLastError() ); + forward2 = LoadLibraryA( forward2_path ); + ok( !!forward2, "couldn't find %s: %u\n", forward2_path, GetLastError() ); + forward3 = LoadLibraryA( forward3_path ); + ok( !!forward3, "couldn't find %s: %u\n", forward3_path, GetLastError() ); + + proc1 = GetProcAddress(forward1, "forward_test_func"); + ok( !!proc1, "cannot resolve forward1!forward_test_func\n"); + proc2 = GetProcAddress(forward2, "forward_test_func"); + ok( !!proc2, "cannot resolve forward2!forward_test_func\n"); + proc3 = GetProcAddress(forward3, "forward_test_func"); + ok( !!proc3, "cannot resolve forward3!forward_test_func\n"); + ok( proc1 == proc3, "forward1!forward_test_func is not equal to forward3!forward_test_func\n"); + ok( proc2 == proc3, "forward2!forward_test_func is not equal to forward3!forward_test_func\n"); + + FreeLibrary( forward1 ); + FreeLibrary( forward2 ); + + todo_wine + ok( !!GetModuleHandleA( "forward1.dll" ), "forward1.dll unexpectedly unloaded\n" ); + todo_wine + ok( !!GetModuleHandleA( "forward2.dll" ), "forward2.dll unexpectedly unloaded\n" ); + + FreeLibrary( forward3 ); + + ok( !GetModuleHandleA( "forward1.dll" ), "forward1.dll unexpectedly kept open\n" ); + ok( !GetModuleHandleA( "forward2.dll" ), "forward2.dll unexpectedly kept open\n" ); + ok( !GetModuleHandleA( "forward3.dll" ), "forward3.dll unexpectedly kept open\n" ); + + DeleteFileA( forward1_path ); + DeleteFileA( forward2_path ); + DeleteFileA( forward3_path ); + RemoveDirectoryA( dir_path ); +} + +static void test_dynamic_forward_export_norefs(void) +{ + CHAR temp_path[MAX_PATH], dir_path[MAX_PATH]; + CHAR forward1_path[MAX_PATH]; + CHAR forward2_path[MAX_PATH]; + CHAR forward3_path[MAX_PATH]; + HMODULE forward1, forward2, forward3; + + GetTempPathA( ARRAY_SIZE(temp_path), temp_path ); + GetTempFileNameA( temp_path, "ldr", GetTickCount() | 1UL, dir_path ); + ok( CreateDirectoryA( dir_path, NULL ), "failed to create dir %s, error %u\n", + dir_path, GetLastError() ); + + snprintf( forward1_path, MAX_PATH, "%s\forward1.dll", dir_path ); + snprintf( forward2_path, MAX_PATH, "%s\forward2.dll", dir_path ); + snprintf( forward3_path, MAX_PATH, "%s\forward3.dll", dir_path ); + extract_resource( "forward1.dll", "TESTDLL", forward1_path ); + extract_resource( "forward2.dll", "TESTDLL", forward2_path ); + extract_resource( "forward3.dll", "TESTDLL", forward3_path ); + + forward1 = LoadLibraryA( forward1_path ); + ok( !!forward1, "couldn't find %s: %u\n", forward1_path, GetLastError() ); + forward2 = LoadLibraryA( forward2_path ); + ok( !!forward2, "couldn't find %s: %u\n", forward2_path, GetLastError() ); + forward3 = LoadLibraryA( forward3_path ); + ok( !!forward3, "couldn't find %s: %u\n", forward3_path, GetLastError() ); + + FreeLibrary( forward1 ); + FreeLibrary( forward3 ); + + ok( !GetModuleHandleA( "forward1.dll" ), "forward1.dll unexpectedly kept open\n" ); + ok( !GetModuleHandleA( "forward3.dll" ), "forward3.dll unexpectedly kept open\n" ); + + FreeLibrary( forward2 ); + + ok( !GetModuleHandleA( "forward2.dll" ), "forward2.dll unexpectedly kept open\n" ); + + DeleteFileA( forward1_path ); + DeleteFileA( forward2_path ); + DeleteFileA( forward3_path ); + RemoveDirectoryA( dir_path ); +} + static void test_image_mapping(const char *dll_name, DWORD scn_page_access, BOOL is_dll) { HANDLE hfile, hmap; @@ -4122,6 +4318,9 @@ START_TEST(loader) test_filenames(); test_ResolveDelayLoadedAPI(); test_ImportDescriptors(); + test_static_forwarded_import_refs(); + test_dynamic_forwarded_import_refs(); + test_dynamic_forward_export_norefs(); test_section_access(); test_import_resolution(); test_ExitProcess();
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52094 Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com --- dlls/kernel32/tests/loader.c | 4 --- dlls/ntdll/loader.c | 69 ++++++++++++++++++++---------------- 2 files changed, 39 insertions(+), 34 deletions(-)
diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c index 97957604aa0..102bb504fb7 100644 --- a/dlls/kernel32/tests/loader.c +++ b/dlls/kernel32/tests/loader.c @@ -1717,9 +1717,7 @@ static void test_static_forwarded_import_refs(void)
if (!skiptest_flag) { - todo_wine ok( !!GetModuleHandleA( "forward1.dll" ), "forward1.dll unexpectedly unloaded\n" ); - todo_wine ok( !!GetModuleHandleA( "forward2.dll" ), "forward2.dll unexpectedly unloaded\n" ); ok( !!GetModuleHandleA( "forward3.dll" ), "forward3.dll unexpectedly unloaded\n" ); } @@ -1778,9 +1776,7 @@ static void test_dynamic_forwarded_import_refs(void) FreeLibrary( forward1 ); FreeLibrary( forward2 );
- todo_wine ok( !!GetModuleHandleA( "forward1.dll" ), "forward1.dll unexpectedly unloaded\n" ); - todo_wine ok( !!GetModuleHandleA( "forward2.dll" ), "forward2.dll unexpectedly unloaded\n" );
FreeLibrary( forward3 ); diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 362e1c66be5..6852f0280af 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -749,7 +749,7 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward, LPCWS { const IMAGE_EXPORT_DIRECTORY *exports; DWORD exp_size; - WINE_MODREF *wm; + WINE_MODREF *wm = NULL, *imp; WCHAR mod_name[256]; const char *end = strrchr(forward, '.'); FARPROC proc = NULL; @@ -757,30 +757,24 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward, LPCWS if (!end) return NULL; if (build_import_name( mod_name, forward, end - forward )) return NULL;
- if (!(wm = find_basename_module( mod_name ))) + imp = get_modref( module ); + TRACE( "delay loading %s for '%s'\n", debugstr_w(mod_name), forward ); + if (load_dll( load_path, mod_name, 0, &wm, imp->system ) == STATUS_SUCCESS && + !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS)) { - WINE_MODREF *imp = get_modref( module ); - TRACE( "delay loading %s for '%s'\n", debugstr_w(mod_name), forward ); - if (load_dll( load_path, mod_name, 0, &wm, imp->system ) == STATUS_SUCCESS && - !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS)) + if ((imports_fixup_done || !current_modref) && + process_attach( wm->ldr.DdagNode, NULL ) != STATUS_SUCCESS) { - if (!imports_fixup_done && current_modref) - { - add_module_dependency( current_modref->ldr.DdagNode, wm->ldr.DdagNode ); - } - else if (process_attach( wm->ldr.DdagNode, NULL ) != STATUS_SUCCESS) - { - LdrUnloadDll( wm->ldr.DllBase ); - wm = NULL; - } + LdrUnloadDll( wm->ldr.DllBase ); + wm = NULL; } + }
- if (!wm) - { - ERR( "module not found for forward '%s' used by %s\n", - forward, debugstr_w(imp->ldr.FullDllName.Buffer) ); - return NULL; - } + if (!wm) + { + ERR( "module not found for forward '%s' used by %s\n", + forward, debugstr_w(imp->ldr.FullDllName.Buffer) ); + return NULL; } if ((exports = RtlImageDirectoryEntryToData( wm->ldr.DllBase, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size ))) @@ -800,6 +794,11 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward, LPCWS " If you are using builtin %s, try using the native one instead.\n", forward, debugstr_w(get_modref(module)->ldr.FullDllName.Buffer), debugstr_w(get_modref(module)->ldr.BaseDllName.Buffer) ); + if (wm) LdrUnloadDll( wm->ldr.DllBase ); + } + else if (current_modref) + { + add_module_dependency( current_modref->ldr.DdagNode, wm->ldr.DdagNode ); } return proc; } @@ -1844,21 +1843,31 @@ NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE module, const ANSI_STRING *name, IMAGE_EXPORT_DIRECTORY *exports; DWORD exp_size; NTSTATUS ret = STATUS_PROCEDURE_NOT_FOUND; + WINE_MODREF *prev, *wm;
RtlEnterCriticalSection( &loader_section );
- /* check if the module itself is invalid to return the proper error */ - if (!get_modref( module )) ret = STATUS_DLL_NOT_FOUND; - else if ((exports = RtlImageDirectoryEntryToData( module, TRUE, - IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size ))) + wm = get_modref( module ); + if (!wm) ret = STATUS_DLL_NOT_FOUND; + else { - void *proc = name ? find_named_export( module, exports, exp_size, name->Buffer, -1, NULL ) - : find_ordinal_export( module, exports, exp_size, ord - exports->Base, NULL ); - if (proc) + prev = current_modref; + current_modref = wm; + + /* check if the module itself is invalid to return the proper error */ + if ((exports = RtlImageDirectoryEntryToData( module, TRUE, + IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size ))) { - *address = proc; - ret = STATUS_SUCCESS; + void *proc = name ? find_named_export( module, exports, exp_size, name->Buffer, -1, NULL ) + : find_ordinal_export( module, exports, exp_size, ord - exports->Base, NULL ); + if (proc) + { + *address = proc; + ret = STATUS_SUCCESS; + } } + + current_modref = prev; }
RtlLeaveCriticalSection( &loader_section );
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=105004
Your paranoid android.
=== w10pro64 (32 bit report) ===
kernel32: loader.c:3026: Test failed: attached thread count should be 2
=== w1064_tsign (64 bit report) ===
kernel32: loader.c:720: Test failed: 1192: wrong status c000012f/c000011b loader.c:720: Test failed: 1197: wrong status c000012f/c000011b loader.c:720: Test failed: 1197: wrong status c000012f/c000011b loader.c:720: Test failed: 1197: wrong status c000012f/c0000131 loader.c:720: Test failed: 1197: wrong status c000012f/c000011b loader.c:720: Test failed: 1197: wrong status c000012f/c000011b loader.c:720: Test failed: 1197: wrong status c000012f/c0000130 loader.c:720: Test failed: 1197: wrong status c000012f/c000011b loader.c:720: Test failed: 1197: wrong status c000012f/c000011b loader.c:720: Test failed: 1197: wrong status c000012f/c000011b loader.c:720: Test failed: 1197: wrong status c000012f/c000011b loader.c:720: Test failed: 1197: wrong status c000012f/c000011b loader.c:720: Test failed: 1197: wrong status c000012f/c000011b loader.c:720: Test failed: 1197: wrong status c000012f/c000011b loader.c:720: Test failed: 1197: wrong status c000012f/c000011b loader.c:720: Test failed: 1197: wrong status c000012f/c000011b loader.c:720: Test failed: 1197: wrong status c000012f/c000011b loader.c:720: Test failed: 1214: wrong status c000012f/c0000130 loader.c:720: Test failed: 1219: wrong status c000012f/c0000130 loader.c:720: Test failed: 1224: wrong status c000012f/c000007b loader.c:720: Test failed: 1229: wrong status c000012f/c000007b loader.c:720: Test failed: 1234: wrong status c000012f/c000007b loader.c:720: Test failed: 1239: wrong status c000012f/c000007b loader.c:720: Test failed: 1244: wrong status c000012f/c000007b loader.c:720: Test failed: 1260: wrong status c000012f/0 loader.c:720: Test failed: 1264: wrong status c000012f/0 loader.c:720: Test failed: 1269: wrong status c000012f/0 loader.c:720: Test failed: 1273: wrong status c000012f/0 loader.c:720: Test failed: 1277: wrong status c000012f/0 loader.c:720: Test failed: 1431: wrong status c000012f/c000007b loader.c:720: Test failed: 1439: wrong status c000012f/c000007b loader.c:720: Test failed: 1444: wrong status c000012f/0 loader.c:724: Test failed: 1444: failed with c000012f expected fallback loader.c:720: Test failed: 1450: wrong status c000012f/0 loader.c:724: Test failed: 1450: failed with c000012f expected fallback loader.c:720: Test failed: 1456: wrong status c000012f/0 loader.c:724: Test failed: 1456: failed with c000012f expected fallback loader.c:720: Test failed: 1463: wrong status c000012f/0 loader.c:724: Test failed: 1463: failed with c000012f expected fallback loader.c:720: Test failed: 1469: wrong status c000012f/0 loader.c:720: Test failed: 1478: wrong status c000012f/0 loader.c:720: Test failed: 1482: wrong status c000012f/0 loader.c:720: Test failed: 1486: wrong status c000012f/0 loader.c:720: Test failed: 1490: wrong status c000012f/0 loader.c:720: Test failed: 1494: wrong status c000012f/0
=== w10pro64_ar (64 bit report) ===
kernel32: loader.c:720: Test failed: 1219: wrong status c000011b/c0000130 loader.c:720: Test failed: 1224: wrong status c000011b/c000007b loader.c:720: Test failed: 1229: wrong status c000011b/c000007b loader.c:720: Test failed: 1234: wrong status c000011b/c000007b
=== w10pro64_he (64 bit report) ===
kernel32: loader.c:720: Test failed: 1219: wrong status c000011b/c0000130 loader.c:720: Test failed: 1224: wrong status c000011b/c000007b loader.c:720: Test failed: 1229: wrong status c000011b/c000007b loader.c:720: Test failed: 1234: wrong status c000011b/c000007b loader.c:720: Test failed: 1239: wrong status c000011b/c000007b loader.c:720: Test failed: 1244: wrong status c000011b/c000007b loader.c:720: Test failed: 1260: wrong status c000011b/0 loader.c:720: Test failed: 1264: wrong status c000011b/0 loader.c:720: Test failed: 1269: wrong status c000011b/0 loader.c:720: Test failed: 1273: wrong status c000011b/0 loader.c:720: Test failed: 1277: wrong status c000011b/0 loader.c:720: Test failed: 1431: wrong status c000011b/c000007b loader.c:720: Test failed: 1439: wrong status c000011b/c000007b loader.c:720: Test failed: 1444: wrong status c000011b/0 loader.c:724: Test failed: 1444: failed with c000011b expected fallback loader.c:720: Test failed: 1450: wrong status c000011b/0 loader.c:724: Test failed: 1450: failed with c000011b expected fallback loader.c:720: Test failed: 1456: wrong status c000011b/0 loader.c:724: Test failed: 1456: failed with c000011b expected fallback loader.c:720: Test failed: 1463: wrong status c000011b/0 loader.c:724: Test failed: 1463: failed with c000011b expected fallback loader.c:720: Test failed: 1469: wrong status c000011b/0 loader.c:720: Test failed: 1478: wrong status c000011b/0
=== w10pro64_ja (64 bit report) ===
kernel32: loader.c:720: Test failed: 1197: wrong status c0000131/c000011b loader.c:720: Test failed: 1197: wrong status c0000131/c000011b loader.c:720: Test failed: 1197: wrong status c0000131/c0000130
Jinoh Kang jinoh.kang.kr@gmail.com writes:
+#define INLINE_IMPORT_BEGIN_PROLOG(id) INLINE_IMPORT_BEGIN_PROLOG_(id) +#define INLINE_IMPORT_BEGIN_PROLOG_(id) \
- __asm__( \
".section \".idata$2\", \"a\"\n\t" /* IMAGE_IMPORT_DESCRIPTOR */ \
".rva .Limport_ilt_" #id "\n\t" /* .OriginalFirstThunk */ \
".long 0\n\t" /* .TimeDateStamp */ \
".long -1\n\t" /* .ForwarderChain */ \
".rva .Limport_dllname_" #id "\n\t" /* .Name */ \
".rva .Limport_iat_" #id "\n\t" /* .FirstThunk */ \
".p2align 2\n\t" /* (section alignment) */ \
".section \".idata$4\", \"a\"\n\t" /* IMAGE_THUNK_DATA (ILT) */ \
IATGAS_EMIT_PTRALIGN "\n\t" \
".Limport_ilt_" #id ":\n\t" \
".section \".idata$5\", \"a\"\n\t" /* IMAGE_THUNK_DATA (IAT) */ \
IATGAS_EMIT_PTRALIGN "\n\t" \
".Limport_iat_" #id ":\n\t" \
".section \".idata$7\", \"a\"\n\t" \
".Limport_dllname_" #id ":\n\t"
+#define INLINE_IMPORT_BEGIN(dll_name) INLINE_IMPORT_BEGIN_PROLOG(__COUNTER__) \
".asciz \"" dll_name "\"\n\t"
+#define INLINE_IMPORT_ENTRY(entry, impsym) \
".section \".idata$4\", \"a\"\n\t" /* IMAGE_THUNK_DATA (ILT) */ \
entry "\n\t" /* .AddressOfData | .Ordinal */ \
".section \".idata$5\", \"a\"\n\t" \
"__imp_" impsym ":\n\t" /* IMAGE_THUNK_DATA (IAT) */ \
entry "\n\t" /* .AddressOfData | .Ordinal */
+#define INLINE_IMPORT_BY_ORDINAL(ordinal, impsym) \
INLINE_IMPORT_ENTRY(IATGAS_EMIT_IMPORT_BY_ORDINAL(ordinal), impsym)
+#define INLINE_IMPORT_BY_NAME(hint, name, impsym) \
INLINE_IMPORT_ENTRY(IATGAS_ZERO_EXTEND_32_TO_PTR(".rva .Limport_procname_" impsym), impsym) \
".section \".idata$6\", \"a\"\n\t" \
".Limport_procname_" impsym ":\n\t" /* IMAGE_IMPORT_BY_NAME */ \
".short " #hint "\n\t" /* .Hint */ \
".asciz \"" name "\"\n\t" /* .Name */ \
".p2align 1\n\t" /* (section alignment) */
+#define INLINE_IMPORT_END() \
".section \".idata$4\", \"a\"\n\t" /* IMAGE_THUNK_DATA (ILT) */ \
IATGAS_ZERO_EXTEND_32_TO_PTR(".long 0") "\n\t" \
".section \".idata$5\", \"a\"\n\t" /* IMAGE_THUNK_DATA (IAT) */ \
IATGAS_ZERO_EXTEND_32_TO_PTR(".long 0") "\n\t" \
".text" \
- );
+#endif
I don't think we want to do that sort of thing, it's really ugly. In any case, you should be able to test that stuff using existing dlls, there are plenty of Windows dlls that use forwards.
It will also have to wait until after code freeze of course.
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=105003
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
kernel32: debugger.c:1027: Test failed: ole32.dll was not reported debugger.c:2122: Test failed: NtSetInformationDebugObject failed c0000008
=== w7u_adm (32 bit report) ===
kernel32: debugger.c:1027: Test failed: ole32.dll was not reported
=== w7u_el (32 bit report) ===
kernel32: debugger.c:1027: Test failed: ole32.dll was not reported
=== w10pro64 (32 bit report) ===
kernel32: debugger.c:681: Test failed: debugger reported 7 failures
=== w1064_tsign (32 bit report) ===
kernel32: loader.c:3030: Test failed: attached thread count should be 2
=== w10pro64 (32 bit report) ===
kernel32: loader.c:3030: Test failed: attached thread count should be 2
=== w10pro64_ja (64 bit report) ===
kernel32: loader.c:720: Test failed: 1219: wrong status c000011b/c0000130 loader.c:720: Test failed: 1224: wrong status c000011b/c000007b loader.c:720: Test failed: 1229: wrong status c000011b/c000007b loader.c:720: Test failed: 1234: wrong status c000011b/c000007b loader.c:720: Test failed: 1239: wrong status c000011b/c000007b loader.c:720: Test failed: 1244: wrong status c000011b/c000007b loader.c:720: Test failed: 1260: wrong status c000011b/0 loader.c:720: Test failed: 1264: wrong status c000011b/0 loader.c:720: Test failed: 1269: wrong status c000011b/0 loader.c:720: Test failed: 1273: wrong status c000011b/0 loader.c:720: Test failed: 1277: wrong status c000011b/0 loader.c:720: Test failed: 1431: wrong status c000011b/c000007b loader.c:720: Test failed: 1439: wrong status c000011b/c000007b loader.c:720: Test failed: 1444: wrong status c000011b/0 loader.c:724: Test failed: 1444: failed with c000011b expected fallback loader.c:720: Test failed: 1450: wrong status c000011b/0 loader.c:724: Test failed: 1450: failed with c000011b expected fallback loader.c:720: Test failed: 1456: wrong status c000011b/0 loader.c:724: Test failed: 1456: failed with c000011b expected fallback loader.c:720: Test failed: 1463: wrong status c000011b/0 loader.c:724: Test failed: 1463: failed with c000011b expected fallback loader.c:720: Test failed: 1469: wrong status c000011b/0 loader.c:720: Test failed: 1478: wrong status c000011b/0 loader.c:720: Test failed: 1482: wrong status c000011b/0 loader.c:720: Test failed: 1486: wrong status c000011b/0 loader.c:720: Test failed: 1490: wrong status c000011b/0 loader.c:720: Test failed: 1494: wrong status c000011b/0
=== w8adm (32 bit report) ===
kernel32: path: Timeout
=== w10pro64_ja (testbot log) ===
WineRunTask.pl:error: The previous 1 run(s) terminated abnormally