dbgeng: Implement GetNumberModules().

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Nikolay Sivov 2019-04-22 09:42:26 +03:00 committed by Alexandre Julliard
parent 4557a007d7
commit 73a8fe94e6
2 changed files with 121 additions and 15 deletions

View File

@ -25,6 +25,7 @@
#include "windef.h"
#include "winbase.h"
#include "winternl.h"
#include "psapi.h"
#include "initguid.h"
#include "dbgeng.h"
@ -44,6 +45,12 @@ struct target_process
unsigned int pid;
unsigned int attach_flags;
HANDLE handle;
struct
{
unsigned int loaded;
unsigned int unloaded;
BOOL initialized;
} modules;
};
struct debug_client
@ -58,6 +65,37 @@ struct debug_client
IDebugEventCallbacks *event_callbacks;
};
static struct target_process *debug_client_get_target(struct debug_client *debug_client)
{
if (list_empty(&debug_client->targets))
return NULL;
return LIST_ENTRY(list_head(&debug_client->targets), struct target_process, entry);
}
static HRESULT debug_target_init_modules_info(struct target_process *target)
{
DWORD needed;
if (target->modules.initialized)
return S_OK;
if (!target->handle)
return E_UNEXPECTED;
needed = 0;
EnumProcessModules(target->handle, NULL, 0, &needed);
if (!needed)
return E_FAIL;
target->modules.loaded = needed / sizeof(HMODULE);
target->modules.unloaded = 0; /* FIXME */
target->modules.initialized = TRUE;
return S_OK;
}
static void debug_client_detach_target(struct target_process *target)
{
NTSTATUS status;
@ -255,7 +293,7 @@ static HRESULT STDMETHODCALLTYPE debugclient_AttachProcess(IDebugClient *iface,
return E_NOTIMPL;
}
if (!(process = heap_alloc(sizeof(*process))))
if (!(process = heap_alloc_zero(sizeof(*process))))
return E_OUTOFMEMORY;
process->pid = pid;
@ -897,9 +935,22 @@ static HRESULT STDMETHODCALLTYPE debugsymbols_GetOffsetByLine(IDebugSymbols3 *if
static HRESULT STDMETHODCALLTYPE debugsymbols_GetNumberModules(IDebugSymbols3 *iface, ULONG *loaded, ULONG *unloaded)
{
FIXME("%p, %p, %p stub.\n", iface, loaded, unloaded);
struct debug_client *debug_client = impl_from_IDebugSymbols3(iface);
static struct target_process *target;
HRESULT hr;
return E_NOTIMPL;
TRACE("%p, %p, %p.\n", iface, loaded, unloaded);
if (!(target = debug_client_get_target(debug_client)))
return E_UNEXPECTED;
if (FAILED(hr = debug_target_init_modules_info(target)))
return hr;
*loaded = target->modules.loaded;
*unloaded = target->modules.unloaded;
return S_OK;
}
static HRESULT STDMETHODCALLTYPE debugsymbols_GetModuleByIndex(IDebugSymbols3 *iface, ULONG index, ULONG64 *base)
@ -2679,15 +2730,13 @@ static HRESULT STDMETHODCALLTYPE debugcontrol_WaitForEvent(IDebugControl2 *iface
/* FIXME: only one target is used currently */
if (list_empty(&debug_client->targets))
if (!(target = debug_client_get_target(debug_client)))
return E_UNEXPECTED;
target = LIST_ENTRY(list_head(&debug_client->targets), struct target_process, entry);
if (target->attach_flags & DEBUG_ATTACH_NONINVASIVE)
{
BOOL suspend = !(target->attach_flags & DEBUG_ATTACH_NONINVASIVE_NO_SUSPEND);
DWORD access = PROCESS_VM_READ | PROCESS_VM_WRITE;
DWORD access = PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_QUERY_LIMITED_INFORMATION;
NTSTATUS status;
if (suspend)

View File

@ -226,17 +226,27 @@ static const IDebugEventCallbacksVtbl event_callbacks_vtbl =
static const char *event_name = "dbgeng_test_event";
static BOOL create_target_process(PROCESS_INFORMATION *info)
{
char path_name[MAX_PATH];
STARTUPINFOA startup;
char **argv;
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);
}
static void test_attach(void)
{
IDebugEventCallbacks event_callbacks = { &event_callbacks_vtbl };
PROCESS_INFORMATION info;
char path_name[MAX_PATH];
IDebugControl *control;
IDebugClient *client;
STARTUPINFOA startup;
BOOL is_debugged;
HANDLE event;
char **argv;
HRESULT hr;
BOOL ret;
@ -252,11 +262,7 @@ static void test_attach(void)
event = CreateEventA(NULL, FALSE, FALSE, event_name);
ok(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]);
ret = CreateProcessA(NULL, path_name, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info),
ret = create_target_process(&info);
ok(ret, "Failed to create target process.\n");
is_debugged = TRUE;
@ -300,6 +306,56 @@ todo_wine
control->lpVtbl->Release(control);
}
static void test_module_information(void)
{
unsigned int loaded, unloaded;
PROCESS_INFORMATION info;
IDebugSymbols *symbols;
IDebugControl *control;
IDebugClient *client;
HANDLE event;
HRESULT hr;
BOOL ret;
hr = DebugCreate(&IID_IDebugClient, (void **)&client);
ok(hr == S_OK, "Failed to create engine object, hr %#x.\n", hr);
hr = client->lpVtbl->QueryInterface(client, &IID_IDebugControl, (void **)&control);
ok(hr == S_OK, "Failed to get interface pointer, hr %#x.\n", hr);
hr = client->lpVtbl->QueryInterface(client, &IID_IDebugSymbols, (void **)&symbols);
ok(hr == S_OK, "Failed to get interface pointer, hr %#x.\n", hr);
event = CreateEventA(NULL, FALSE, FALSE, event_name);
ok(event != NULL, "Failed to create event.\n");
ret = create_target_process(&info);
ok(ret, "Failed to create target process.\n");
hr = client->lpVtbl->AttachProcess(client, 0, info.dwProcessId, DEBUG_ATTACH_NONINVASIVE);
ok(hr == S_OK, "Failed to attach to process, hr %#x.\n", hr);
hr = control->lpVtbl->WaitForEvent(control, 0, INFINITE);
ok(hr == S_OK, "Waiting for event failed, hr %#x.\n", hr);
/* Number of modules. */
hr = symbols->lpVtbl->GetNumberModules(symbols, &loaded, &unloaded);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
hr = client->lpVtbl->DetachProcesses(client);
ok(hr == S_OK, "Failed to detach, hr %#x.\n", hr);
SetEvent(event);
winetest_wait_child_process(info.hProcess);
CloseHandle(info.hProcess);
CloseHandle(info.hThread);
client->lpVtbl->Release(client);
control->lpVtbl->Release(control);
symbols->lpVtbl->Release(symbols);
}
static void target_proc(void)
{
HANDLE event = OpenEventA(SYNCHRONIZE, FALSE, event_name);
@ -330,4 +386,5 @@ START_TEST(dbgeng)
test_engine_options();
test_attach();
test_module_information();
}