dbgeng: Implement GetNumberModules().
Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
4557a007d7
commit
73a8fe94e6
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue