diff --git a/dlls/imagehlp/modify.c b/dlls/imagehlp/modify.c index 434a666ae94..d740d221bfc 100644 --- a/dlls/imagehlp/modify.c +++ b/dlls/imagehlp/modify.c @@ -44,15 +44,90 @@ BOOL WINAPI BindImage( /*********************************************************************** * BindImageEx (IMAGEHLP.@) */ -BOOL WINAPI BindImageEx( - DWORD Flags, PCSTR ImageName, PCSTR DllPath, PCSTR SymbolPath, - PIMAGEHLP_STATUS_ROUTINE StatusRoutine) +BOOL WINAPI BindImageEx(DWORD flags, const char *module, const char *dll_path, + const char *symbol_path, PIMAGEHLP_STATUS_ROUTINE cb) { - FIXME("(%d, %s, %s, %s, %p): stub\n", - Flags, debugstr_a(ImageName), debugstr_a(DllPath), - debugstr_a(SymbolPath), StatusRoutine - ); - return TRUE; + const IMAGE_IMPORT_DESCRIPTOR *import; + LOADED_IMAGE image; + ULONG size; + + TRACE("flags %#x, module %s, dll_path %s, symbol_path %s, cb %p.\n", + flags, debugstr_a(module), debugstr_a(dll_path), debugstr_a(symbol_path), cb); + + if (!(flags & BIND_NO_UPDATE)) + FIXME("Image modification is not implemented.\n"); + if (flags & ~BIND_NO_UPDATE) + FIXME("Ignoring flags %#x.\n", flags); + + if (!MapAndLoad(module, dll_path, &image, TRUE, TRUE)) + return FALSE; + + if (!(import = ImageDirectoryEntryToData(image.MappedAddress, FALSE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size))) + { + UnMapAndLoad(&image); + return TRUE; /* no imports */ + } + + if (image.FileHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC) + { + FIXME("Unhandled architecture %#x.\n", image.FileHeader->OptionalHeader.Magic); + UnMapAndLoad(&image); + return TRUE; + } + + for (; import->Name && import->FirstThunk; ++import) + { + char full_path[MAX_PATH]; + IMAGE_THUNK_DATA *thunk; + const char *dll_name; + DWORD thunk_rva; + + if (!(dll_name = ImageRvaToVa(image.FileHeader, image.MappedAddress, import->Name, 0))) + { + ERR("Failed to get VA for import name RVA %#x.\n", import->Name); + continue; + } + + if (cb) cb(BindImportModule, module, dll_name, 0, 0); + + if (!SearchPathA(dll_path, dll_name, 0, sizeof(full_path), full_path, 0)) + { + ERR("Import %s was not found.\n", debugstr_a(dll_path)); + continue; + } + + thunk_rva = import->OriginalFirstThunk ? import->OriginalFirstThunk : import->FirstThunk; + if (!(thunk = ImageRvaToVa(image.FileHeader, image.MappedAddress, thunk_rva, 0))) + { + ERR("Failed to get VA for import thunk RVA %#x.\n", thunk_rva); + continue; + } + + for (; thunk->u1.Ordinal; ++thunk) + { + if (IMAGE_SNAP_BY_ORDINAL(thunk->u1.Ordinal)) + { + /* FIXME: We apparently need to subtract the actual module's + * ordinal base. */ + FIXME("Ordinal imports are not implemented.\n"); + } + else + { + IMAGE_IMPORT_BY_NAME *name; + + if (!(name = ImageRvaToVa(image.FileHeader, image.MappedAddress, thunk->u1.AddressOfData, 0))) + { + ERR("Failed to get VA for name RVA %#x.\n", thunk->u1.AddressOfData); + continue; + } + + if (cb) cb(BindImportProcedure, module, full_path, 0, (ULONG_PTR)name->Name); + } + } + } + + UnMapAndLoad(&image); + return TRUE; } diff --git a/dlls/imagehlp/tests/image.c b/dlls/imagehlp/tests/image.c index 888744ac203..e2aa9485510 100644 --- a/dlls/imagehlp/tests/image.c +++ b/dlls/imagehlp/tests/image.c @@ -372,7 +372,7 @@ static BOOL WINAPI bind_image_cb(IMAGEHLP_STATUS_REASON reason, const char *file char full_path[MAX_PATH]; BOOL ret; - ok(!!va, "expected nonzero VA\n"); + todo_wine ok(!!va, "expected nonzero VA\n"); ret = SearchPathA(NULL, last_module, ".dll", sizeof(full_path), full_path, NULL); ok(ret, "got error %u\n", GetLastError()); ok(!strcmp(module, full_path), "expected %s, got %s\n", debugstr_a(full_path), debugstr_a(module)); @@ -408,15 +408,15 @@ static void test_bind_image_ex(void) SetLastError(0xdeadbeef); ret = BindImageEx(BIND_ALL_IMAGES | BIND_NO_BOUND_IMPORTS | BIND_NO_UPDATE, "nonexistent.dll", 0, 0, bind_image_cb); - todo_wine ok(!ret, "expected failure\n"); - todo_wine ok(GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_INVALID_PARAMETER, + ok(!ret, "expected failure\n"); + ok(GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_INVALID_PARAMETER, "got error %u\n", GetLastError()); ret = BindImageEx(BIND_ALL_IMAGES | BIND_NO_BOUND_IMPORTS | BIND_NO_UPDATE, filename, NULL, NULL, bind_image_cb); ok(ret, "got error %u\n", GetLastError()); - todo_wine ok(got_SysAllocString == 1, "got %u imports of SysAllocString\n", got_SysAllocString); - todo_wine ok(got_GetOpenFileNameA == 1, "got %u imports of GetOpenFileNameA\n", got_GetOpenFileNameA); + ok(got_SysAllocString == 1, "got %u imports of SysAllocString\n", got_SysAllocString); + ok(got_GetOpenFileNameA == 1, "got %u imports of GetOpenFileNameA\n", got_GetOpenFileNameA); todo_wine ok(got_SHRegGetIntW == 1, "got %u imports of SHRegGetIntW\n", got_SHRegGetIntW); ret = DeleteFileA(filename);