Module: wine Branch: oldstable Commit: 71c9a0f604c534af060c8fd175ffec21db0596ea URL: https://source.winehq.org/git/wine.git/?a=commit;h=71c9a0f604c534af060c8fd17...
Author: André Hentschel nerv@dawncrow.de Date: Sat Nov 10 22:29:27 2018 +0100
ntdll: Call system hook in LdrResolveDelayLoadedAPI when dll hook is missing.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46089 Signed-off-by: André Hentschel nerv@dawncrow.de Signed-off-by: Alexandre Julliard julliard@winehq.org (cherry picked from commit 95fa795fa1f8b416af097b6186859ec32ea316d9) Signed-off-by: Michael Stefaniuc mstefani@winehq.org
---
dlls/kernel32/tests/loader.c | 53 +++++++++++++++++++++++++++++++++++++++----- dlls/ntdll/loader.c | 18 +++++++++++++-- include/delayloadhandler.h | 1 + 3 files changed, 64 insertions(+), 8 deletions(-)
diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c index 7066bca..2551d48 100644 --- a/dlls/kernel32/tests/loader.c +++ b/dlls/kernel32/tests/loader.c @@ -47,7 +47,7 @@ struct PROCESS_BASIC_INFORMATION_PRIVATE };
static LONG *child_failures; -static WORD cb_count; +static WORD cb_count, cb_count_sys; static DWORD page_size;
static NTSTATUS (WINAPI *pNtCreateSection)(HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, @@ -67,7 +67,8 @@ static NTSTATUS (WINAPI *pLdrUnlockLoaderLock)(ULONG, ULONG_PTR); static void (WINAPI *pRtlAcquirePebLock)(void); static void (WINAPI *pRtlReleasePebLock)(void); static PVOID (WINAPI *pResolveDelayLoadedAPI)(PVOID, PCIMAGE_DELAYLOAD_DESCRIPTOR, - PDELAYLOAD_FAILURE_DLL_CALLBACK, PVOID, + PDELAYLOAD_FAILURE_DLL_CALLBACK, + PDELAYLOAD_FAILURE_SYSTEM_ROUTINE, PIMAGE_THUNK_DATA ThunkAddress,ULONG); static PVOID (WINAPI *pRtlImageDirectoryEntryToData)(HMODULE,BOOL,WORD,ULONG *); static DWORD (WINAPI *pFlsAlloc)(PFLS_CALLBACK_FUNCTION); @@ -2986,6 +2987,14 @@ static PVOID WINAPI failuredllhook(ULONG ul, DELAYLOAD_INFO* pd) return (void*)0xdeadbeef; }
+static PVOID WINAPI failuresyshook(const char *dll, const char *function) +{ + ok(!strcmp(dll, "secur32.dll"), "wrong dll: %s\n", dll); + ok(!((ULONG_PTR)function >> 16), "expected ordinal, got %p\n", function); + cb_count_sys++; + return (void*)0x12345678; +} + static void test_ResolveDelayLoadedAPI(void) { static const char test_dll[] = "secur32.dll"; @@ -3220,8 +3229,9 @@ static void test_ResolveDelayLoadedAPI(void) load = (void *)GetProcAddress(htarget, (char*)iibn->Name); }
- cb_count = 0; - ret = pResolveDelayLoadedAPI(hlib, delaydir, failuredllhook, NULL, &itda[i], 0); + /* test without failure dll callback */ + cb_count = cb_count_sys = 0; + ret = pResolveDelayLoadedAPI(hlib, delaydir, NULL, failuresyshook, &itda[i], 0); if (td[i].succeeds) { ok(ret != NULL, "Test %u: ResolveDelayLoadedAPI failed\n", i); @@ -3229,11 +3239,42 @@ static void test_ResolveDelayLoadedAPI(void) ok(ret == (void*)itda[i].u1.AddressOfData, "Test %u: expected %p, got %p\n", i, ret, (void*)itda[i].u1.AddressOfData); ok(!cb_count, "Test %u: Wrong callback count: %d\n", i, cb_count); + ok(!cb_count_sys, "Test %u: Wrong sys callback count: %d\n", i, cb_count_sys); } else { - ok(ret == (void*)0xdeadbeef, "Test %u: ResolveDelayLoadedAPI succeeded with %p\n", i, ret); - ok(cb_count, "Test %u: Wrong callback count: %d\n", i, cb_count); + ok(ret == (void*)0x12345678, "Test %u: ResolveDelayLoadedAPI succeeded with %p\n", i, ret); + ok(!cb_count, "Test %u: Wrong callback count: %d\n", i, cb_count); + ok(cb_count_sys == 1, "Test %u: Wrong sys callback count: %d\n", i, cb_count_sys); + } + + /* test with failure dll callback */ + cb_count = cb_count_sys = 0; + ret = pResolveDelayLoadedAPI(hlib, delaydir, failuredllhook, failuresyshook, &itda[i], 0); + if (td[i].succeeds) + { + ok(ret != NULL, "Test %u: ResolveDelayLoadedAPI failed\n", i); + ok(ret == load, "Test %u: expected %p, got %p\n", i, load, ret); + ok(ret == (void*)itda[i].u1.AddressOfData, "Test %u: expected %p, got %p\n", + i, ret, (void*)itda[i].u1.AddressOfData); + ok(!cb_count, "Test %u: Wrong callback count: %d\n", i, cb_count); + ok(!cb_count_sys, "Test %u: Wrong sys callback count: %d\n", i, cb_count_sys); + } + else + { + if (ret == (void*)0x12345678) + { + /* Win10+ sometimes buffers the address of the stub function */ + ok(!cb_count, "Test %u: Wrong callback count: %d\n", i, cb_count); + ok(!cb_count_sys, "Test %u: Wrong sys callback count: %d\n", i, cb_count_sys); + } + else if (ret == (void*)0xdeadbeef) + { + ok(cb_count == 1, "Test %u: Wrong callback count: %d\n", i, cb_count); + ok(!cb_count_sys, "Test %u: Wrong sys callback count: %d\n", i, cb_count_sys); + } + else + ok(0, "Test %u: ResolveDelayLoadedAPI succeeded with %p\n", i, ret); } } delaydir++; diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index 53280a4..3972ac6 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -2683,7 +2683,8 @@ BOOLEAN WINAPI RtlDllShutdownInProgress(void) * LdrResolveDelayLoadedAPI (NTDLL.@) */ void* WINAPI LdrResolveDelayLoadedAPI( void* base, const IMAGE_DELAYLOAD_DESCRIPTOR* desc, - PDELAYLOAD_FAILURE_DLL_CALLBACK dllhook, void* syshook, + PDELAYLOAD_FAILURE_DLL_CALLBACK dllhook, + PDELAYLOAD_FAILURE_SYSTEM_ROUTINE syshook, IMAGE_THUNK_DATA* addr, ULONG flags ) { IMAGE_THUNK_DATA *pIAT, *pINT; @@ -2741,7 +2742,20 @@ fail: delayinfo.TargetModuleBase = *phmod; delayinfo.Unused = NULL; delayinfo.LastError = nts; - return dllhook(4, &delayinfo); + + if (dllhook) + return dllhook(4, &delayinfo); + + if (IMAGE_SNAP_BY_ORDINAL(pINT[id].u1.Ordinal)) + { + DWORD_PTR ord = LOWORD(pINT[id].u1.Ordinal); + return syshook(name, (const char *)ord); + } + else + { + const IMAGE_IMPORT_BY_NAME* iibn = get_rva(base, pINT[id].u1.AddressOfData); + return syshook(name, (const char *)iibn->Name); + } }
/****************************************************************** diff --git a/include/delayloadhandler.h b/include/delayloadhandler.h index 06b6589..e833611 100644 --- a/include/delayloadhandler.h +++ b/include/delayloadhandler.h @@ -47,6 +47,7 @@ typedef struct _DELAYLOAD_INFO } DELAYLOAD_INFO, *PDELAYLOAD_INFO;
typedef PVOID (WINAPI *PDELAYLOAD_FAILURE_DLL_CALLBACK)(ULONG, PDELAYLOAD_INFO); +typedef PVOID (WINAPI *PDELAYLOAD_FAILURE_SYSTEM_ROUTINE)(LPCSTR, LPCSTR);
#ifdef __cplusplus }