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); ...@@ -39,6 +39,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbgeng);
extern NTSTATUS WINAPI NtSuspendProcess(HANDLE handle); extern NTSTATUS WINAPI NtSuspendProcess(HANDLE handle);
extern NTSTATUS WINAPI NtResumeProcess(HANDLE handle); extern NTSTATUS WINAPI NtResumeProcess(HANDLE handle);
struct module_info
{
DEBUG_MODULE_PARAMETERS params;
};
struct target_process struct target_process
{ {
struct list entry; struct list entry;
...@@ -47,6 +52,7 @@ struct target_process ...@@ -47,6 +52,7 @@ struct target_process
HANDLE handle; HANDLE handle;
struct struct
{ {
struct module_info *info;
unsigned int loaded; unsigned int loaded;
unsigned int unloaded; unsigned int unloaded;
BOOL initialized; BOOL initialized;
...@@ -75,6 +81,9 @@ static struct target_process *debug_client_get_target(struct debug_client *debug ...@@ -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) static HRESULT debug_target_init_modules_info(struct target_process *target)
{ {
unsigned int i, count;
HMODULE *modules;
MODULEINFO info;
DWORD needed; DWORD needed;
if (target->modules.initialized) if (target->modules.initialized)
...@@ -88,7 +97,35 @@ static HRESULT debug_target_init_modules_info(struct target_process *target) ...@@ -88,7 +97,35 @@ static HRESULT debug_target_init_modules_info(struct target_process *target)
if (!needed) if (!needed)
return E_FAIL; 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.unloaded = 0; /* FIXME */
target->modules.initialized = TRUE; target->modules.initialized = TRUE;
...@@ -96,6 +133,17 @@ static HRESULT debug_target_init_modules_info(struct target_process *target) ...@@ -96,6 +133,17 @@ static HRESULT debug_target_init_modules_info(struct target_process *target)
return S_OK; 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) static void debug_client_detach_target(struct target_process *target)
{ {
NTSTATUS status; NTSTATUS status;
...@@ -185,6 +233,12 @@ static ULONG STDMETHODCALLTYPE debugclient_AddRef(IDebugClient *iface) ...@@ -185,6 +233,12 @@ static ULONG STDMETHODCALLTYPE debugclient_AddRef(IDebugClient *iface)
return refcount; 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) static ULONG STDMETHODCALLTYPE debugclient_Release(IDebugClient *iface)
{ {
struct debug_client *debug_client = impl_from_IDebugClient(iface); struct debug_client *debug_client = impl_from_IDebugClient(iface);
...@@ -199,7 +253,7 @@ static ULONG STDMETHODCALLTYPE debugclient_Release(IDebugClient *iface) ...@@ -199,7 +253,7 @@ static ULONG STDMETHODCALLTYPE debugclient_Release(IDebugClient *iface)
{ {
debug_client_detach_target(cur); debug_client_detach_target(cur);
list_remove(&cur->entry); list_remove(&cur->entry);
heap_free(cur); debug_target_free(cur);
} }
if (debug_client->event_callbacks) if (debug_client->event_callbacks)
debug_client->event_callbacks->lpVtbl->Release(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 ...@@ -955,9 +1009,21 @@ static HRESULT STDMETHODCALLTYPE debugsymbols_GetNumberModules(IDebugSymbols3 *i
static HRESULT STDMETHODCALLTYPE debugsymbols_GetModuleByIndex(IDebugSymbols3 *iface, ULONG index, ULONG64 *base) 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, static HRESULT STDMETHODCALLTYPE debugsymbols_GetModuleByModuleName(IDebugSymbols3 *iface, const char *name,
......
...@@ -224,23 +224,36 @@ static const IDebugEventCallbacksVtbl event_callbacks_vtbl = ...@@ -224,23 +224,36 @@ static const IDebugEventCallbacksVtbl event_callbacks_vtbl =
event_callbacks_ChangeSymbolState, event_callbacks_ChangeSymbolState,
}; };
static const char *event_name = "dbgeng_test_event"; static BOOL create_target_process(const char *event_name, PROCESS_INFORMATION *info)
static BOOL create_target_process(PROCESS_INFORMATION *info)
{ {
static const char *event_target_ready_name = "dbgeng_test_target_ready_event";
char path_name[MAX_PATH]; char path_name[MAX_PATH];
STARTUPINFOA startup; STARTUPINFOA startup;
HANDLE ready_event;
char **argv; 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); winetest_get_mainargs(&argv);
memset(&startup, 0, sizeof(startup)); memset(&startup, 0, sizeof(startup));
startup.cb = sizeof(startup); startup.cb = sizeof(startup);
sprintf(path_name, "%s dbgeng target", argv[0]); sprintf(path_name, "%s dbgeng target %s %s", argv[0], event_name, event_target_ready_name);
return CreateProcessA(NULL, path_name, NULL, NULL, FALSE, 0, NULL, NULL, &startup, info); 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 void test_attach(void)
{ {
static const char *event_name = "dbgeng_test_event";
IDebugEventCallbacks event_callbacks = { &event_callbacks_vtbl }; IDebugEventCallbacks event_callbacks = { &event_callbacks_vtbl };
PROCESS_INFORMATION info; PROCESS_INFORMATION info;
IDebugControl *control; IDebugControl *control;
...@@ -262,7 +275,7 @@ static void test_attach(void) ...@@ -262,7 +275,7 @@ static void test_attach(void)
event = CreateEventA(NULL, FALSE, FALSE, event_name); event = CreateEventA(NULL, FALSE, FALSE, event_name);
ok(event != NULL, "Failed to create event.\n"); 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"); ok(ret, "Failed to create target process.\n");
is_debugged = TRUE; is_debugged = TRUE;
...@@ -308,11 +321,13 @@ todo_wine ...@@ -308,11 +321,13 @@ todo_wine
static void test_module_information(void) static void test_module_information(void)
{ {
static const char *event_name = "dbgeng_test_event";
unsigned int loaded, unloaded; unsigned int loaded, unloaded;
PROCESS_INFORMATION info; PROCESS_INFORMATION info;
IDebugSymbols *symbols; IDebugSymbols *symbols;
IDebugControl *control; IDebugControl *control;
IDebugClient *client; IDebugClient *client;
ULONG64 base;
HANDLE event; HANDLE event;
HRESULT hr; HRESULT hr;
BOOL ret; BOOL ret;
...@@ -329,9 +344,12 @@ static void test_module_information(void) ...@@ -329,9 +344,12 @@ static void test_module_information(void)
event = CreateEventA(NULL, FALSE, FALSE, event_name); event = CreateEventA(NULL, FALSE, FALSE, event_name);
ok(event != NULL, "Failed to create event.\n"); 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"); 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); hr = client->lpVtbl->AttachProcess(client, 0, info.dwProcessId, DEBUG_ATTACH_NONINVASIVE);
ok(hr == S_OK, "Failed to attach to process, hr %#x.\n", hr); ok(hr == S_OK, "Failed to attach to process, hr %#x.\n", hr);
...@@ -341,6 +359,16 @@ static void test_module_information(void) ...@@ -341,6 +359,16 @@ static void test_module_information(void)
/* Number of modules. */ /* Number of modules. */
hr = symbols->lpVtbl->GetNumberModules(symbols, &loaded, &unloaded); hr = symbols->lpVtbl->GetNumberModules(symbols, &loaded, &unloaded);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr); 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); hr = client->lpVtbl->DetachProcesses(client);
ok(hr == S_OK, "Failed to detach, hr %#x.\n", hr); ok(hr == S_OK, "Failed to detach, hr %#x.\n", hr);
...@@ -356,19 +384,26 @@ static void test_module_information(void) ...@@ -356,19 +384,26 @@ static void test_module_information(void)
symbols->lpVtbl->Release(symbols); 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 (;;) for (;;)
{ {
if (WaitForSingleObject(event, 100) == WAIT_OBJECT_0) if (WaitForSingleObject(terminate_event, 100) == WAIT_OBJECT_0)
break; break;
} }
CloseHandle(event); CloseHandle(terminate_event);
CloseHandle(ready_event);
} }
START_TEST(dbgeng) START_TEST(dbgeng)
...@@ -378,9 +413,9 @@ START_TEST(dbgeng) ...@@ -378,9 +413,9 @@ START_TEST(dbgeng)
argc = winetest_get_mainargs(&argv); 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; 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