Signed-off-by: Jinoh Kang jinoh.kang.kr@gmail.com ---
Notes: v3 -> v4: - iatgas.h - LLVM(Clang), ARM, ARM64 support - Use __ASM_NAME macro - Don't fail test on MSVC - Don't end asm macros with "\n\t"
v4 -> v5: - iatgas.h - mark idata sections as RO - loader.c - test for forward export itself
v5 -> v6: - loader.c - Fix compilation warning in format string
v6 -> v7: - forward4.c - fix building without MinGW
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 308cf1a44a0..8c5ab88d9d7 100644 --- a/dlls/kernel32/tests/loader.c +++ b/dlls/kernel32/tests/loader.c @@ -1641,6 +1641,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; @@ -4106,6 +4302,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 8c5ab88d9d7..6a19ed0e858 100644 --- a/dlls/kernel32/tests/loader.c +++ b/dlls/kernel32/tests/loader.c @@ -1716,9 +1716,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" ); } @@ -1777,9 +1775,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 d11f3f0f79d..d251ee8b283 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=104103
Your paranoid android.
=== w7u_adm (32 bit report) ===
kernel32: comm.c:886: Test failed: WaitCommEvent used 1497 ms for waiting
=== w7u_2qxl (32 bit report) ===
kernel32: debugger.c:1023: Test failed: ole32.dll was not reported
=== w7u_adm (32 bit report) ===
kernel32: debugger.c:1023: Test failed: ole32.dll was not reported
=== w7u_el (32 bit report) ===
kernel32: debugger.c:1023: Test failed: ole32.dll was not reported
=== w1064_tsign (64 bit report) ===
kernel32: debugger.c:1516: Test failed: dwDebugEventCode = 6 expected 1 debugger.c:1516: Test failed: ExceptionCode = 3b4 expected 80000003 debugger.c:1517: Test failed: dwDebugEventCode = 1 expected 4 debugger.c:1569: Test failed: dwThreadId differs: 1c58 (was 1c5c) debugger.c:1721: Test failed: dwDebugEventCode = 4
=== w8adm (32 bit report) ===
kernel32: path: Timeout
=== debian11 (32 bit French report) ===
kernel32: comm.c:918: Test failed: OutQueue should not be empty