Commit d33180ae authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

dbgeng: Implement GetModuleByIndex().

parent 73a8fe94
......@@ -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,
......
......@@ -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;
}
......
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