From: André Hentschel Subject: ntdll: Call system hook in LdrResolveDelayLoadedAPI when dll hook is missing Message-Id: <899a5431-9d80-0842-fa2e-2fd4e8229117@dawncrow.de> Date: Tue, 6 Nov 2018 21:50:18 +0100 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46089 Signed-off-by: Andr� Hentschel --- dlls/kernel32/tests/loader.c | 39 +++++++++++++++++++++++++++++++++--- dlls/ntdll/loader.c | 23 +++++++++++++++++++-- include/delayloadhandler.h | 1 + 3 files changed, 58 insertions(+), 5 deletions(-) diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c index bc88c5f6cf..f5204fec0d 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 NULL; +} + static void test_ResolveDelayLoadedAPI(void) { static const char test_dll[] = "secur32.dll"; @@ -3573,8 +3582,30 @@ static void test_ResolveDelayLoadedAPI(void) load = (void *)GetProcAddress(htarget, (char*)iibn->Name); } + /* test without failure dll callback */ + cb_count = 0; + 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); + 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 + { + ok(!ret, "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, "Test %u: Wrong sys callback count: %d\n", i, cb_count_sys); + } + + /* test with failure dll callback */ cb_count = 0; - ret = pResolveDelayLoadedAPI(hlib, delaydir, failuredllhook, NULL, &itda[i], 0); + 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); @@ -3582,11 +3613,13 @@ 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(!cb_count_sys, "Test %u: Wrong sys callback count: %d\n", i, cb_count_sys); } } delaydir++; diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c index c5e8d0d7c1..838be31c11 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,25 @@ fail: delayinfo.TargetModuleBase = *phmod; delayinfo.Unused = NULL; delayinfo.LastError = nts; - return dllhook(4, &delayinfo); + + if (!dllhook && syshook) + { + if (IMAGE_SNAP_BY_ORDINAL(pINT[id].u1.Ordinal)) + { + DWORD_PTR ord = LOWORD(pINT[id].u1.Ordinal); + dllhook = syshook(name, (char*)ord); + } + else + { + const IMAGE_IMPORT_BY_NAME* iibn = get_rva(base, pINT[id].u1.AddressOfData); + dllhook = syshook(name, (char*)iibn->Name); + } + } + + if (dllhook) + return dllhook(4, &delayinfo); + else + return NULL; } /****************************************************************** diff --git a/include/delayloadhandler.h b/include/delayloadhandler.h index 06b658990c..e8336111ff 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 } -- 2.17.1