=?UTF-8?Q?Andr=C3=A9=20Hentschel=20?=: ntdll: Call system hook in LdrResolveDelayLoadedAPI when dll hook is missing.
Alexandre Julliard
julliard at winehq.org
Mon Nov 12 16:26:55 CST 2018
Module: wine
Branch: master
Commit: 95fa795fa1f8b416af097b6186859ec32ea316d9
URL: https://source.winehq.org/git/wine.git/?a=commit;h=95fa795fa1f8b416af097b6186859ec32ea316d9
Author: André Hentschel <nerv at 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 at dawncrow.de>
Signed-off-by: Alexandre Julliard <julliard at 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 bc88c5f..01c7cfa 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 c5e8d0d..b00a5f8 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 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
}
More information about the wine-cvs
mailing list