kernel32/tests: Add tests for ResolveDelayLoadedAPI
André Hentschel
nerv at dawncrow.de
Mon Sep 2 17:48:44 CDT 2013
---
dlls/kernel32/tests/loader.c | 149 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 149 insertions(+)
diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c
index 3b72cc8..0bbd120 100644
--- a/dlls/kernel32/tests/loader.c
+++ b/dlls/kernel32/tests/loader.c
@@ -41,8 +41,53 @@ struct PROCESS_BASIC_INFORMATION_PRIVATE
ULONG_PTR InheritedFromUniqueProcessId;
};
+typedef struct _IMAGE_DELAYLOAD_DESCRIPTOR_PRIVATE
+{
+ union
+ {
+ DWORD AllAttributes;
+ struct
+ {
+ DWORD RvaBased:1;
+ DWORD ReservedAttributes:31;
+ } DUMMYSTRUCTNAME;
+ } Attributes;
+
+ DWORD DllNameRVA;
+ DWORD ModuleHandleRVA;
+ DWORD ImportAddressTableRVA;
+ DWORD ImportNameTableRVA;
+ DWORD BoundImportAddressTableRVA;
+ DWORD UnloadInformationTableRVA;
+ DWORD TimeDateStamp;
+} IMAGE_DELAYLOAD_DESCRIPTOR_PRIVATE;
+
+typedef struct _DELAYLOAD_PROC_DESCRIPTOR_PRIVATE
+{
+ ULONG ImportDescribedByName;
+ union {
+ LPCSTR Name;
+ ULONG Ordinal;
+ } Description;
+} DELAYLOAD_PROC_DESCRIPTOR_PRIVATE;
+
+typedef struct _DELAYLOAD_INFO_PRIVATE
+{
+ ULONG Size;
+ const IMAGE_DELAYLOAD_DESCRIPTOR_PRIVATE* DelayloadDescriptor;
+ PIMAGE_THUNK_DATA ThunkAddress;
+ LPCSTR TargetDllName;
+ DELAYLOAD_PROC_DESCRIPTOR_PRIVATE TargetApiDescriptor;
+ PVOID TargetModuleBase;
+ PVOID Unused;
+ ULONG LastError;
+} DELAYLOAD_INFO_PRIVATE;
+
+typedef PVOID (WINAPI *PDELAYLOAD_FAILURE_DLL_CALLBACK_PRIVATE)(ULONG, DELAYLOAD_INFO_PRIVATE*);
+
static BOOL is_child;
static LONG *child_failures;
+static WORD cb_count;
static NTSTATUS (WINAPI *pNtMapViewOfSection)(HANDLE, HANDLE, PVOID *, ULONG, SIZE_T, const LARGE_INTEGER *, SIZE_T *, ULONG, ULONG, ULONG);
static NTSTATUS (WINAPI *pNtUnmapViewOfSection)(HANDLE, PVOID);
@@ -57,6 +102,9 @@ static NTSTATUS (WINAPI *pLdrLockLoaderLock)(ULONG, ULONG *, ULONG *);
static NTSTATUS (WINAPI *pLdrUnlockLoaderLock)(ULONG, ULONG);
static void (WINAPI *pRtlAcquirePebLock)(void);
static void (WINAPI *pRtlReleasePebLock)(void);
+static PVOID (WINAPI *pResolveDelayLoadedAPI)(PVOID, const IMAGE_DELAYLOAD_DESCRIPTOR_PRIVATE*,
+ PDELAYLOAD_FAILURE_DLL_CALLBACK_PRIVATE,
+ PVOID, PIMAGE_THUNK_DATA ThunkAddress,ULONG);
static PVOID RVAToAddr(DWORD_PTR rva, HMODULE module)
{
@@ -2184,6 +2232,105 @@ if (0)
ok(ret, "DeleteFile error %d\n", GetLastError());
}
+static PVOID WINAPI failuredllhook(ULONG ul, DELAYLOAD_INFO_PRIVATE* pd)
+{
+ cb_count++;
+ return NULL;
+}
+
+static void test_ResolveDelayLoadedAPI(void)
+{
+ HMODULE hlib;
+ int i;
+ static const char* td[] =
+ {
+ "advapi32.dll",
+ "comdlg32.dll",
+ };
+
+ if (!pResolveDelayLoadedAPI)
+ {
+ todo_wine win_skip("ResolveDelayLoadedAPI is not available\n");
+ return;
+ }
+
+ if (0) /* crashes on native */
+ {
+ SetLastError(0xdeadbeef);
+ ok(!pResolveDelayLoadedAPI(NULL, NULL, NULL, NULL, NULL, 0),
+ "ResolveDelayLoadedAPI succeeded\n");
+ ok(GetLastError() == 0xdeadbeef, "GetLastError changed to %x\n", GetLastError());
+
+ cb_count = 0;
+ SetLastError(0xdeadbeef);
+ ok(!pResolveDelayLoadedAPI(NULL, NULL, failuredllhook, NULL, NULL, 0),
+ "ResolveDelayLoadedAPI succeeded\n");
+ ok(GetLastError() == 0xdeadbeef, "GetLastError changed to %x\n", GetLastError());
+ ok(cb_count == 1, "Wrong callback count: %d\n", cb_count);
+ }
+
+ for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
+ {
+ IMAGE_DELAYLOAD_DESCRIPTOR_PRIVATE *delaydir;
+ ULONG size;
+
+ SetLastError(0xdeadbeef);
+ hlib = LoadLibrary(td[i]);
+ ok(hlib != NULL, "LoadLibrary error %u\n", GetLastError());
+ if (!hlib)
+ {
+ skip("couldn't load %s.\n", td[i]);
+ continue;
+ }
+
+ delaydir = RtlImageDirectoryEntryToData(hlib, TRUE, IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT, &size);
+ if (!delaydir)
+ {
+ skip("haven't found section for delay import directory in %s.\n", td[i]);
+ FreeLibrary(hlib);
+ continue;
+ }
+
+ for (;;)
+ {
+ const IMAGE_THUNK_DATA *itdn;
+ IMAGE_THUNK_DATA *itda;
+ HMODULE htarget;
+ int j;
+
+ if (!delaydir->DllNameRVA ||
+ !delaydir->ImportAddressTableRVA ||
+ !delaydir->ImportNameTableRVA) break;
+
+ itdn = RVAToAddr(delaydir->ImportNameTableRVA, hlib);
+ itda = RVAToAddr(delaydir->ImportAddressTableRVA, hlib);
+ htarget = LoadLibrary(RVAToAddr(delaydir->DllNameRVA, hlib));
+ for (j = 0; itdn[j].u1.Ordinal; j++)
+ {
+ void *ret, *load;
+
+ if (IMAGE_SNAP_BY_ORDINAL(itdn[j].u1.Ordinal))
+ load = (void *)GetProcAddress(htarget, (LPSTR)IMAGE_ORDINAL(itdn[j].u1.Ordinal));
+ else
+ {
+ const IMAGE_IMPORT_BY_NAME* iibn = RVAToAddr(itdn[j].u1.AddressOfData, hlib);
+ load = (void *)GetProcAddress(htarget, (char*)iibn->Name);
+ }
+
+ cb_count = 0;
+ ret = pResolveDelayLoadedAPI(hlib, delaydir, failuredllhook, NULL, &itda[j], 0);
+ ok(ret != NULL, "ResolveDelayLoadedAPI failed\n");
+ ok(ret == load, "expected %p, got %p\n", ret, load);
+ ok(ret == (void*)itda[j].u1.AddressOfData, "expected %p, got %p\n",
+ ret, (void*)itda[j].u1.AddressOfData);
+ ok(!cb_count, "Wrong callback count: %d\n", cb_count);
+ }
+ delaydir++;
+ }
+ FreeLibrary(hlib);
+ }
+}
+
START_TEST(loader)
{
int argc;
@@ -2203,6 +2350,7 @@ START_TEST(loader)
pLdrUnlockLoaderLock = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "LdrUnlockLoaderLock");
pRtlAcquirePebLock = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlAcquirePebLock");
pRtlReleasePebLock = (void *)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlReleasePebLock");
+ pResolveDelayLoadedAPI = (void *)GetProcAddress(GetModuleHandle("kernel32.dll"), "ResolveDelayLoadedAPI");
mapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, "winetest_loader");
ok(mapping != 0, "CreateFileMapping failed\n");
@@ -2227,4 +2375,5 @@ START_TEST(loader)
test_ImportDescriptors();
test_section_access();
test_ExitProcess();
+ test_ResolveDelayLoadedAPI();
}
--
1.8.1.2
More information about the wine-patches
mailing list