Bernhard Reiter : imagehlp: Partially implement BindImageEx().

Alexandre Julliard julliard at winehq.org
Mon Jun 7 15:02:05 CDT 2021


Module: wine
Branch: stable
Commit: f40379a9d1762de99f6b6f624c6f57a90be648d8
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=f40379a9d1762de99f6b6f624c6f57a90be648d8

Author: Bernhard Reiter <ockham at raz.or.at>
Date:   Sat Feb 13 11:30:11 2021 -0600

imagehlp: Partially implement BindImageEx().

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=3591
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
(cherry picked from commit d129a89d228190baeb8983ecfc18e093255148b9)
Signed-off-by: Michael Stefaniuc <mstefani at winehq.org>

---

 dlls/imagehlp/modify.c      | 91 +++++++++++++++++++++++++++++++++++++++++----
 dlls/imagehlp/tests/image.c | 10 ++---
 2 files changed, 88 insertions(+), 13 deletions(-)

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);




More information about the wine-cvs mailing list