Nikolay Sivov : dbgeng: Implement GetModuleByIndex().

Alexandre Julliard julliard at winehq.org
Mon Apr 22 16:30:38 CDT 2019


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

Author: Nikolay Sivov <nsivov at codeweavers.com>
Date:   Mon Apr 22 09:42:27 2019 +0300

dbgeng: Implement GetModuleByIndex().

Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/dbgeng/dbgeng.c       | 74 +++++++++++++++++++++++++++++++++++++++++++---
 dlls/dbgeng/tests/dbgeng.c | 63 ++++++++++++++++++++++++++++++---------
 2 files changed, 119 insertions(+), 18 deletions(-)

diff --git a/dlls/dbgeng/dbgeng.c b/dlls/dbgeng/dbgeng.c
index 077de3b..d4f8205 100644
--- a/dlls/dbgeng/dbgeng.c
+++ b/dlls/dbgeng/dbgeng.c
@@ -39,6 +39,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbgeng);
 extern NTSTATUS WINAPI NtSuspendProcess(HANDLE handle);
 extern NTSTATUS WINAPI NtResumeProcess(HANDLE handle);
 
+struct module_info
+{
+    DEBUG_MODULE_PARAMETERS params;
+};
+
 struct target_process
 {
     struct list entry;
@@ -47,6 +52,7 @@ struct target_process
     HANDLE handle;
     struct
     {
+        struct module_info *info;
         unsigned int loaded;
         unsigned int unloaded;
         BOOL initialized;
@@ -75,6 +81,9 @@ static struct target_process *debug_client_get_target(struct debug_client *debug
 
 static HRESULT debug_target_init_modules_info(struct target_process *target)
 {
+    unsigned int i, count;
+    HMODULE *modules;
+    MODULEINFO info;
     DWORD needed;
 
     if (target->modules.initialized)
@@ -88,7 +97,35 @@ static HRESULT debug_target_init_modules_info(struct target_process *target)
     if (!needed)
         return E_FAIL;
 
-    target->modules.loaded = needed / sizeof(HMODULE);
+    count = needed / sizeof(HMODULE);
+
+    if (!(modules = heap_alloc(count * sizeof(*modules))))
+        return E_OUTOFMEMORY;
+
+    if (!(target->modules.info = heap_alloc_zero(count * sizeof(*target->modules.info))))
+    {
+        heap_free(modules);
+        return E_OUTOFMEMORY;
+    }
+
+    if (EnumProcessModules(target->handle, modules, count * sizeof(*modules), &needed))
+    {
+        for (i = 0; i < count; ++i)
+        {
+            if (!GetModuleInformation(target->handle, modules[i], &info, sizeof(info)))
+            {
+                WARN("Failed to get module information, error %d.\n", GetLastError());
+                continue;
+            }
+
+            target->modules.info[i].params.Base = (ULONG_PTR)info.lpBaseOfDll;
+            target->modules.info[i].params.Size = info.SizeOfImage;
+        }
+    }
+
+    heap_free(modules);
+
+    target->modules.loaded = count;
     target->modules.unloaded = 0; /* FIXME */
 
     target->modules.initialized = TRUE;
@@ -96,6 +133,17 @@ static HRESULT debug_target_init_modules_info(struct target_process *target)
     return S_OK;
 }
 
+static const struct module_info *debug_target_get_module_info(struct target_process *target, unsigned int i)
+{
+    if (FAILED(debug_target_init_modules_info(target)))
+        return NULL;
+
+    if (i >= target->modules.loaded)
+        return NULL;
+
+    return &target->modules.info[i];
+}
+
 static void debug_client_detach_target(struct target_process *target)
 {
     NTSTATUS status;
@@ -185,6 +233,12 @@ static ULONG STDMETHODCALLTYPE debugclient_AddRef(IDebugClient *iface)
     return refcount;
 }
 
+static void debug_target_free(struct target_process *target)
+{
+    heap_free(target->modules.info);
+    heap_free(target);
+}
+
 static ULONG STDMETHODCALLTYPE debugclient_Release(IDebugClient *iface)
 {
     struct debug_client *debug_client = impl_from_IDebugClient(iface);
@@ -199,7 +253,7 @@ static ULONG STDMETHODCALLTYPE debugclient_Release(IDebugClient *iface)
         {
             debug_client_detach_target(cur);
             list_remove(&cur->entry);
-            heap_free(cur);
+            debug_target_free(cur);
         }
         if (debug_client->event_callbacks)
             debug_client->event_callbacks->lpVtbl->Release(debug_client->event_callbacks);
@@ -955,9 +1009,21 @@ static HRESULT STDMETHODCALLTYPE debugsymbols_GetNumberModules(IDebugSymbols3 *i
 
 static HRESULT STDMETHODCALLTYPE debugsymbols_GetModuleByIndex(IDebugSymbols3 *iface, ULONG index, ULONG64 *base)
 {
-    FIXME("%p, %u, %p stub.\n", iface, index, base);
+    struct debug_client *debug_client = impl_from_IDebugSymbols3(iface);
+    const struct module_info *info;
+    struct target_process *target;
 
-    return E_NOTIMPL;
+    TRACE("%p, %u, %p.\n", iface, index, base);
+
+    if (!(target = debug_client_get_target(debug_client)))
+        return E_UNEXPECTED;
+
+    if (!(info = debug_target_get_module_info(target, index)))
+        return E_INVALIDARG;
+
+    *base = info->params.Base;
+
+    return S_OK;
 }
 
 static HRESULT STDMETHODCALLTYPE debugsymbols_GetModuleByModuleName(IDebugSymbols3 *iface, const char *name,
diff --git a/dlls/dbgeng/tests/dbgeng.c b/dlls/dbgeng/tests/dbgeng.c
index 6e6e2d3..74f9e7c 100644
--- a/dlls/dbgeng/tests/dbgeng.c
+++ b/dlls/dbgeng/tests/dbgeng.c
@@ -224,23 +224,36 @@ static const IDebugEventCallbacksVtbl event_callbacks_vtbl =
     event_callbacks_ChangeSymbolState,
 };
 
-static const char *event_name = "dbgeng_test_event";
-
-static BOOL create_target_process(PROCESS_INFORMATION *info)
+static BOOL create_target_process(const char *event_name, PROCESS_INFORMATION *info)
 {
+    static const char *event_target_ready_name = "dbgeng_test_target_ready_event";
     char path_name[MAX_PATH];
     STARTUPINFOA startup;
+    HANDLE ready_event;
     char **argv;
+    BOOL ret;
+
+    ready_event = CreateEventA(NULL, FALSE, FALSE, event_target_ready_name);
+    ok(ready_event != NULL, "Failed to create event.\n");
 
     winetest_get_mainargs(&argv);
     memset(&startup, 0, sizeof(startup));
     startup.cb = sizeof(startup);
-    sprintf(path_name, "%s dbgeng target", argv[0]);
-    return CreateProcessA(NULL, path_name, NULL, NULL, FALSE, 0, NULL, NULL, &startup, info);
+    sprintf(path_name, "%s dbgeng target %s %s", argv[0], event_name, event_target_ready_name);
+    ret = CreateProcessA(NULL, path_name, NULL, NULL, FALSE, 0, NULL, NULL, &startup, info);
+    if (ret)
+    {
+        WaitForSingleObject(ready_event, INFINITE);
+    }
+
+    CloseHandle(ready_event);
+
+    return ret;
 }
 
 static void test_attach(void)
 {
+    static const char *event_name = "dbgeng_test_event";
     IDebugEventCallbacks event_callbacks = { &event_callbacks_vtbl };
     PROCESS_INFORMATION info;
     IDebugControl *control;
@@ -262,7 +275,7 @@ static void test_attach(void)
     event = CreateEventA(NULL, FALSE, FALSE, event_name);
     ok(event != NULL, "Failed to create event.\n");
 
-    ret = create_target_process(&info);
+    ret = create_target_process(event_name, &info);
     ok(ret, "Failed to create target process.\n");
 
     is_debugged = TRUE;
@@ -308,11 +321,13 @@ todo_wine
 
 static void test_module_information(void)
 {
+    static const char *event_name = "dbgeng_test_event";
     unsigned int loaded, unloaded;
     PROCESS_INFORMATION info;
     IDebugSymbols *symbols;
     IDebugControl *control;
     IDebugClient *client;
+    ULONG64 base;
     HANDLE event;
     HRESULT hr;
     BOOL ret;
@@ -329,9 +344,12 @@ static void test_module_information(void)
     event = CreateEventA(NULL, FALSE, FALSE, event_name);
     ok(event != NULL, "Failed to create event.\n");
 
-    ret = create_target_process(&info);
+    ret = create_target_process(event_name, &info);
     ok(ret, "Failed to create target process.\n");
 
+    hr = control->lpVtbl->SetEngineOptions(control, DEBUG_ENGOPT_INITIAL_BREAK);
+    ok(hr == S_OK, "Failed to set engine options, hr %#x.\n", hr);
+
     hr = client->lpVtbl->AttachProcess(client, 0, info.dwProcessId, DEBUG_ATTACH_NONINVASIVE);
     ok(hr == S_OK, "Failed to attach to process, hr %#x.\n", hr);
 
@@ -341,6 +359,16 @@ static void test_module_information(void)
     /* Number of modules. */
     hr = symbols->lpVtbl->GetNumberModules(symbols, &loaded, &unloaded);
     ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(loaded > 0, "Unexpected module count %u.\n", loaded);
+
+    /* Module base. */
+    hr = symbols->lpVtbl->GetModuleByIndex(symbols, loaded, &base);
+    ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
+
+    base = 0;
+    hr = symbols->lpVtbl->GetModuleByIndex(symbols, 0, &base);
+    ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+    ok(!!base, "Unexpected module base.\n");
 
     hr = client->lpVtbl->DetachProcesses(client);
     ok(hr == S_OK, "Failed to detach, hr %#x.\n", hr);
@@ -356,19 +384,26 @@ static void test_module_information(void)
     symbols->lpVtbl->Release(symbols);
 }
 
-static void target_proc(void)
+static void target_proc(const char *event_name, const char *event_ready_name)
 {
-    HANDLE event = OpenEventA(SYNCHRONIZE, FALSE, event_name);
+    HANDLE terminate_event, ready_event;
 
-    ok(event != NULL, "Failed to open event handle.\n");
+    terminate_event = OpenEventA(SYNCHRONIZE, FALSE, event_name);
+    ok(terminate_event != NULL, "Failed to open event handle.\n");
+
+    ready_event = OpenEventA(EVENT_MODIFY_STATE, FALSE, event_ready_name);
+    ok(ready_event != NULL, "Failed to open event handle.\n");
+
+    SetEvent(ready_event);
 
     for (;;)
     {
-        if (WaitForSingleObject(event, 100) == WAIT_OBJECT_0)
+        if (WaitForSingleObject(terminate_event, 100) == WAIT_OBJECT_0)
             break;
     }
 
-    CloseHandle(event);
+    CloseHandle(terminate_event);
+    CloseHandle(ready_event);
 }
 
 START_TEST(dbgeng)
@@ -378,9 +413,9 @@ START_TEST(dbgeng)
 
     argc = winetest_get_mainargs(&argv);
 
-    if (argc >= 3 && !strcmp(argv[2], "target"))
+    if (argc > 4 && !strcmp(argv[2], "target"))
     {
-        target_proc();
+        target_proc(argv[3], argv[4]);
         return;
     }
 




More information about the wine-cvs mailing list