From 95fa795fa1f8b416af097b6186859ec32ea316d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Hentschel?= Date: Sat, 10 Nov 2018 22:29:27 +0100 Subject: [PATCH] ntdll: Call system hook in LdrResolveDelayLoadedAPI when dll hook is missing. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46089 Signed-off-by: André Hentschel Signed-off-by: Alexandre Julliard --- 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 bc88c5f6cf4..01c7cfa8a91 100644 --- a/dlls/kernel32/tests/loader.c +++ b/dlls/kernel32/tests/loader.c @@ -48,7 +48,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 BOOL is_win64 = sizeof(void *) > sizeof(int); static BOOL is_wow64; @@ -70,7 +70,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); @@ -3339,6 +3340,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"; @@ -3573,8 +3582,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); @@ -3582,11 +3592,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 c5e8d0d7c18..b00a5f889fd 100644 --- a/dlls/ntdll/loader.c +++ b/dlls/ntdll/loader.c @@ -2934,7 +2934,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; @@ -2992,7 +2993,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 06b658990c4..e8336111ff7 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 }