Commit cb1806db authored by André Hentschel's avatar André Hentschel Committed by Alexandre Julliard

kernel32/tests: Test ResolveDelayLoadedAPI with generated dll.

parent 58e83ebd
...@@ -2197,12 +2197,37 @@ static PVOID WINAPI failuredllhook(ULONG ul, DELAYLOAD_INFO* pd) ...@@ -2197,12 +2197,37 @@ static PVOID WINAPI failuredllhook(ULONG ul, DELAYLOAD_INFO* pd)
static void test_ResolveDelayLoadedAPI(void) static void test_ResolveDelayLoadedAPI(void)
{ {
static const char test_dll[] = "secur32.dll";
static const char test_func[] = "SealMessage";
static const char filler[0x1000];
char temp_path[MAX_PATH];
char dll_name[MAX_PATH];
IMAGE_DELAYLOAD_DESCRIPTOR idd, *delaydir;
IMAGE_THUNK_DATA itd32;
HANDLE hfile;
HMODULE hlib; HMODULE hlib;
int i; DWORD dummy, file_size, i;
static const char* td[] = WORD hint = 0;
BOOL ret;
static const struct test_data
{ {
"advapi32.dll", BOOL func;
"comdlg32.dll", UINT_PTR ordinal;
BOOL succeeds;
} td[] =
{
{
TRUE, 0, TRUE
},
{
FALSE, IMAGE_ORDINAL_FLAG | 2, TRUE
},
{
FALSE, IMAGE_ORDINAL_FLAG | 5, TRUE
},
{
FALSE, IMAGE_ORDINAL_FLAG | 0, FALSE
},
}; };
if (!pResolveDelayLoadedAPI) if (!pResolveDelayLoadedAPI)
...@@ -2226,66 +2251,198 @@ static void test_ResolveDelayLoadedAPI(void) ...@@ -2226,66 +2251,198 @@ static void test_ResolveDelayLoadedAPI(void)
ok(cb_count == 1, "Wrong callback count: %d\n", cb_count); ok(cb_count == 1, "Wrong callback count: %d\n", cb_count);
} }
for (i = 0; i < sizeof(td)/sizeof(td[0]); i++) GetTempPathA(MAX_PATH, temp_path);
GetTempFileNameA(temp_path, "ldr", 0, dll_name);
trace("creating %s\n", dll_name);
hfile = CreateFileA(dll_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
if (hfile == INVALID_HANDLE_VALUE)
{ {
IMAGE_DELAYLOAD_DESCRIPTOR *delaydir; ok(0, "could not create %s\n", dll_name);
ULONG size; return;
}
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, &dos_header, sizeof(dos_header), &dummy, NULL);
ok(ret, "WriteFile error %d\n", GetLastError());
nt_header.FileHeader.NumberOfSections = 2;
nt_header.FileHeader.SizeOfOptionalHeader = sizeof(IMAGE_OPTIONAL_HEADER);
nt_header.OptionalHeader.SectionAlignment = 0x1000;
nt_header.OptionalHeader.FileAlignment = 0x1000;
nt_header.OptionalHeader.SizeOfImage = sizeof(dos_header) + sizeof(nt_header) + sizeof(IMAGE_SECTION_HEADER) + 0x2200;
nt_header.OptionalHeader.SizeOfHeaders = sizeof(dos_header) + sizeof(nt_header) + 2 * sizeof(IMAGE_SECTION_HEADER);
nt_header.OptionalHeader.NumberOfRvaAndSizes = 15;
nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress = 0x1000;
nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].Size = 0x100;
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, &nt_header, sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER), &dummy, NULL);
ok(ret, "WriteFile error %d\n", GetLastError());
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, &nt_header.OptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER), &dummy, NULL);
ok(ret, "WriteFile error %d\n", GetLastError());
/* sections */
section.PointerToRawData = nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress;
section.VirtualAddress = nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress;
section.Misc.VirtualSize = nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].Size;
section.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, &section, sizeof(section), &dummy, NULL);
ok(ret, "WriteFile error %d\n", GetLastError());
section.PointerToRawData = 0x2000;
section.VirtualAddress = 0x2000;
i = sizeof(td)/sizeof(td[0]);
section.Misc.VirtualSize = sizeof(test_dll) + sizeof(hint) + sizeof(test_func) + sizeof(HMODULE) +
2 * (i + 1) * sizeof(IMAGE_THUNK_DATA);
ok(section.Misc.VirtualSize <= 0x1000, "Too much tests, add a new section!\n");
section.Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, &section, sizeof(section), &dummy, NULL);
ok(ret, "WriteFile error %d\n", GetLastError());
/* fill up to delay data */
file_size = GetFileSize(hfile, NULL);
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, filler,
nt_header.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress - file_size,
&dummy, NULL);
ok(ret, "WriteFile error %d\n", GetLastError());
/* delay data */
idd.Attributes.AllAttributes = 1;
idd.DllNameRVA = 0x2000;
idd.ModuleHandleRVA = idd.DllNameRVA + sizeof(test_dll) + sizeof(hint) + sizeof(test_func);
idd.ImportAddressTableRVA = idd.ModuleHandleRVA + sizeof(HMODULE);
idd.ImportNameTableRVA = idd.ImportAddressTableRVA + (i + 1) * sizeof(IMAGE_THUNK_DATA);
idd.BoundImportAddressTableRVA = 0;
idd.UnloadInformationTableRVA = 0;
idd.TimeDateStamp = 0;
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, &idd, sizeof(idd), &dummy, NULL);
ok(ret, "WriteFile error %d\n", GetLastError());
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, filler, sizeof(idd), &dummy, NULL);
ok(ret, "WriteFile error %d\n", GetLastError());
/* fill up to extended delay data */
file_size = GetFileSize(hfile, NULL);
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, filler, idd.DllNameRVA - file_size, &dummy, NULL);
ok(ret, "WriteFile error %d\n", GetLastError());
/* extended delay data */
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, test_dll, sizeof(test_dll), &dummy, NULL);
ok(ret, "WriteFile error %d\n", GetLastError());
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, &hint, sizeof(hint), &dummy, NULL);
ok(ret, "WriteFile error %d\n", GetLastError());
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, test_func, sizeof(test_func), &dummy, NULL);
ok(ret, "WriteFile error %d\n", GetLastError());
file_size = GetFileSize(hfile, NULL);
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, filler, idd.ImportNameTableRVA - file_size, &dummy, NULL);
ok(ret, "WriteFile error %d\n", GetLastError());
for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
{
if (td[i].func)
itd32.u1.AddressOfData = idd.DllNameRVA + sizeof(test_dll);
else
itd32.u1.Ordinal = td[i].ordinal;
SetLastError(0xdeadbeef); SetLastError(0xdeadbeef);
hlib = LoadLibraryA(td[i]); ret = WriteFile(hfile, &itd32, sizeof(itd32), &dummy, NULL);
ok(hlib != NULL, "LoadLibrary error %u\n", GetLastError()); ok(ret, "WriteFile error %d\n", GetLastError());
if (!hlib) }
{
skip("couldn't load %s.\n", td[i]);
continue;
}
delaydir = RtlImageDirectoryEntryToData(hlib, TRUE, IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT, &size); itd32.u1.Ordinal = 0;
if (!delaydir) SetLastError(0xdeadbeef);
{ ret = WriteFile(hfile, &itd32, sizeof(itd32), &dummy, NULL);
skip("haven't found section for delay import directory in %s.\n", td[i]); ok(ret, "WriteFile error %d\n", GetLastError());
FreeLibrary(hlib);
continue;
}
for (;;) /* fill up to eof */
file_size = GetFileSize(hfile, NULL);
SetLastError(0xdeadbeef);
ret = WriteFile(hfile, filler, section.VirtualAddress + section.Misc.VirtualSize - file_size, &dummy, NULL);
ok(ret, "WriteFile error %d\n", GetLastError());
CloseHandle(hfile);
SetLastError(0xdeadbeef);
hlib = LoadLibraryA(dll_name);
ok(hlib != NULL, "LoadLibrary error %u\n", GetLastError());
if (!hlib)
{
skip("couldn't load %s.\n", dll_name);
DeleteFileA(dll_name);
return;
}
delaydir = RtlImageDirectoryEntryToData(hlib, TRUE, IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT, &file_size);
if (!delaydir)
{
skip("haven't found section for delay import directory.\n");
FreeLibrary(hlib);
DeleteFileA(dll_name);
return;
}
for (;;)
{
IMAGE_THUNK_DATA *itdn, *itda;
HMODULE htarget;
if (!delaydir->DllNameRVA ||
!delaydir->ImportAddressTableRVA ||
!delaydir->ImportNameTableRVA) break;
itdn = RVAToAddr(delaydir->ImportNameTableRVA, hlib);
itda = RVAToAddr(delaydir->ImportAddressTableRVA, hlib);
htarget = LoadLibraryA(RVAToAddr(delaydir->DllNameRVA, hlib));
for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
{ {
const IMAGE_THUNK_DATA *itdn; void *ret, *load;
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 = LoadLibraryA(RVAToAddr(delaydir->DllNameRVA, hlib));
for (j = 0; itdn[j].u1.Ordinal; j++)
{
void *ret, *load;
if (IMAGE_SNAP_BY_ORDINAL(itdn[j].u1.Ordinal)) if (IMAGE_SNAP_BY_ORDINAL(itdn[i].u1.Ordinal))
load = (void *)GetProcAddress(htarget, (LPSTR)IMAGE_ORDINAL(itdn[j].u1.Ordinal)); load = (void *)GetProcAddress(htarget, (LPSTR)IMAGE_ORDINAL(itdn[i].u1.Ordinal));
else else
{ {
const IMAGE_IMPORT_BY_NAME* iibn = RVAToAddr(itdn[j].u1.AddressOfData, hlib); const IMAGE_IMPORT_BY_NAME* iibn = RVAToAddr(itdn[i].u1.AddressOfData, hlib);
load = (void *)GetProcAddress(htarget, (char*)iibn->Name); load = (void *)GetProcAddress(htarget, (char*)iibn->Name);
} }
cb_count = 0; cb_count = 0;
ret = pResolveDelayLoadedAPI(hlib, delaydir, failuredllhook, NULL, &itda[j], 0); ret = pResolveDelayLoadedAPI(hlib, delaydir, failuredllhook, NULL, &itda[i], 0);
ok(ret != NULL, "ResolveDelayLoadedAPI failed\n"); if (td[i].succeeds)
ok(ret == load, "expected %p, got %p\n", ret, load); {
ok(ret == (void*)itda[j].u1.AddressOfData, "expected %p, got %p\n", ok(ret != NULL, "Test %u: ResolveDelayLoadedAPI failed\n", i);
ret, (void*)itda[j].u1.AddressOfData); ok(ret == load, "Test %u: expected %p, got %p\n", i, load, ret);
ok(!cb_count, "Wrong callback count: %d\n", cb_count); 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);
}
else
{
ok(ret == NULL, "Test %u: ResolveDelayLoadedAPI succeeded\n", i);
ok(cb_count, "Test %u: Wrong callback count: %d\n", i, cb_count);
} }
delaydir++;
} }
FreeLibrary(hlib); delaydir++;
} }
FreeLibrary(hlib);
trace("deleting %s\n", dll_name);
DeleteFileA(dll_name);
} }
START_TEST(loader) START_TEST(loader)
...@@ -2330,8 +2487,8 @@ START_TEST(loader) ...@@ -2330,8 +2487,8 @@ START_TEST(loader)
} }
test_Loader(); test_Loader();
test_ResolveDelayLoadedAPI();
test_ImportDescriptors(); test_ImportDescriptors();
test_section_access(); test_section_access();
test_ExitProcess(); test_ExitProcess();
test_ResolveDelayLoadedAPI();
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment