Commit 8f3e72ed authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

dbgeng: Keep a list of processes to attach to.

parent f1562cfd
......@@ -31,9 +31,17 @@
#include "wine/debug.h"
#include "wine/heap.h"
#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL(dbgeng);
struct target_process
{
struct list entry;
unsigned int pid;
unsigned int attach_flags;
};
struct debug_client
{
IDebugClient IDebugClient_iface;
......@@ -42,6 +50,7 @@ struct debug_client
IDebugControl2 IDebugControl2_iface;
LONG refcount;
ULONG engine_options;
struct list targets;
};
static struct debug_client *impl_from_IDebugClient(IDebugClient *iface)
......@@ -113,11 +122,19 @@ static ULONG STDMETHODCALLTYPE debugclient_Release(IDebugClient *iface)
{
struct debug_client *debug_client = impl_from_IDebugClient(iface);
ULONG refcount = InterlockedDecrement(&debug_client->refcount);
struct target_process *cur, *cur2;
TRACE("%p, %d.\n", debug_client, refcount);
if (!refcount)
{
LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &debug_client->targets, struct target_process, entry)
{
list_remove(&cur->entry);
heap_free(cur);
}
heap_free(debug_client);
}
return refcount;
}
......@@ -195,9 +212,26 @@ static HRESULT STDMETHODCALLTYPE debugclient_GetRunningProcessDescription(IDebug
static HRESULT STDMETHODCALLTYPE debugclient_AttachProcess(IDebugClient *iface, ULONG64 server, ULONG pid, ULONG flags)
{
FIXME("%p, %s, %u, %#x stub.\n", iface, wine_dbgstr_longlong(server), pid, flags);
struct debug_client *debug_client = impl_from_IDebugClient(iface);
struct target_process *process;
return E_NOTIMPL;
TRACE("%p, %s, %u, %#x.\n", iface, wine_dbgstr_longlong(server), pid, flags);
if (server)
{
FIXME("Remote debugging is not supported.\n");
return E_NOTIMPL;
}
if (!(process = heap_alloc(sizeof(*process))))
return E_OUTOFMEMORY;
process->pid = pid;
process->attach_flags = flags;
list_add_head(&debug_client->targets, &process->entry);
return S_OK;
}
static HRESULT STDMETHODCALLTYPE debugclient_CreateProcess(IDebugClient *iface, ULONG64 server, char *cmdline,
......@@ -2142,6 +2176,7 @@ HRESULT WINAPI DebugCreate(REFIID riid, void **obj)
debug_client->IDebugSymbols_iface.lpVtbl = &debugsymbolsvtbl;
debug_client->IDebugControl2_iface.lpVtbl = &debugcontrolvtbl;
debug_client->refcount = 1;
list_init(&debug_client->targets);
unk = (IUnknown *)&debug_client->IDebugClient_iface;
......
......@@ -17,6 +17,7 @@
*/
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "windef.h"
......@@ -99,7 +100,237 @@ static void test_engine_options(void)
control->lpVtbl->Release(control);
}
static HRESULT WINAPI event_callbacks_QueryInterface(IDebugEventCallbacks *iface, REFIID riid, void **out)
{
if (IsEqualIID(riid, &IID_IDebugEventCallbacks) ||
IsEqualIID(riid, &IID_IUnknown))
{
*out = iface;
iface->lpVtbl->AddRef(iface);
return S_OK;
}
*out = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI event_callbacks_AddRef(IDebugEventCallbacks *iface)
{
return 2;
}
static ULONG WINAPI event_callbacks_Release(IDebugEventCallbacks *iface)
{
return 1;
}
static HRESULT WINAPI event_callbacks_GetInterestMask(IDebugEventCallbacks *iface, ULONG *mask)
{
*mask = ~0u;
return S_OK;
}
static HRESULT WINAPI event_callbacks_Breakpoint(IDebugEventCallbacks *iface, PDEBUG_BREAKPOINT breakpoint)
{
return E_NOTIMPL;
}
static HRESULT WINAPI event_callbacks_Exception(IDebugEventCallbacks *iface, EXCEPTION_RECORD64 *exception,
ULONG first_chance)
{
return E_NOTIMPL;
}
static HRESULT WINAPI event_callbacks_CreateThread(IDebugEventCallbacks *iface, ULONG64 handle, ULONG64 data_offset,
ULONG64 start_offset)
{
return E_NOTIMPL;
}
static HRESULT WINAPI event_callbacks_ExitThread(IDebugEventCallbacks *iface, ULONG exit_code)
{
return E_NOTIMPL;
}
static HRESULT WINAPI event_callbacks_CreateProcess(IDebugEventCallbacks *iface, ULONG64 image_handle, ULONG64 handle,
ULONG64 base_offset, ULONG module_size, const char *module_name, const char *image_name, ULONG checksum,
ULONG timedatestamp, ULONG64 initial_thread_handle, ULONG64 thread_data_offset, ULONG64 start_offset)
{
return E_NOTIMPL;
}
static HRESULT WINAPI event_callbacks_ExitProcess(IDebugEventCallbacks *iface, ULONG exit_code)
{
return E_NOTIMPL;
}
static HRESULT WINAPI event_callbacks_LoadModule(IDebugEventCallbacks *iface, ULONG64 image_handle,
ULONG64 base_offset, ULONG module_size, const char *module_name, const char *image_name, ULONG checksum,
ULONG timedatestamp)
{
return E_NOTIMPL;
}
static HRESULT WINAPI event_callbacks_UnloadModule(IDebugEventCallbacks *iface, const char *image_basename,
ULONG64 base_offset)
{
return E_NOTIMPL;
}
static HRESULT WINAPI event_callbacks_SystemError(IDebugEventCallbacks *iface, ULONG error, ULONG level)
{
return E_NOTIMPL;
}
static HRESULT WINAPI event_callbacks_SessionStatus(IDebugEventCallbacks *iface, ULONG status)
{
return E_NOTIMPL;
}
static HRESULT WINAPI event_callbacks_ChangeDebuggeeState(IDebugEventCallbacks *iface, ULONG flags, ULONG64 argument)
{
return E_NOTIMPL;
}
static HRESULT WINAPI event_callbacks_ChangeEngineState(IDebugEventCallbacks *iface, ULONG flags, ULONG64 argument)
{
return E_NOTIMPL;
}
static HRESULT WINAPI event_callbacks_ChangeSymbolState(IDebugEventCallbacks *iface, ULONG flags, ULONG64 argument)
{
return E_NOTIMPL;
}
static const IDebugEventCallbacksVtbl event_callbacks_vtbl =
{
event_callbacks_QueryInterface,
event_callbacks_AddRef,
event_callbacks_Release,
event_callbacks_GetInterestMask,
event_callbacks_Breakpoint,
event_callbacks_Exception,
event_callbacks_CreateThread,
event_callbacks_ExitThread,
event_callbacks_CreateProcess,
event_callbacks_ExitProcess,
event_callbacks_LoadModule,
event_callbacks_UnloadModule,
event_callbacks_SystemError,
event_callbacks_SessionStatus,
event_callbacks_ChangeDebuggeeState,
event_callbacks_ChangeEngineState,
event_callbacks_ChangeSymbolState,
};
static const char *event_name = "dbgeng_test_event";
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;
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->SetEventCallbacks(client, &event_callbacks);
todo_wine
ok(hr == S_OK, "Failed to set event callbacks, hr %#x.\n", hr);
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),
ok(ret, "Failed to create target process.\n");
is_debugged = TRUE;
CheckRemoteDebuggerPresent(info.hProcess, &is_debugged);
ok(!is_debugged, "Unexpected mode.\n");
/* Non-invasive mode. */
hr = client->lpVtbl->AttachProcess(client, 0, info.dwProcessId, DEBUG_ATTACH_NONINVASIVE);
ok(hr == S_OK, "Failed to attach to process, hr %#x.\n", hr);
is_debugged = TRUE;
ret = CheckRemoteDebuggerPresent(info.hProcess, &is_debugged);
ok(ret, "Failed to check target status.\n");
ok(!is_debugged, "Unexpected mode.\n");
hr = control->lpVtbl->WaitForEvent(control, 0, INFINITE);
todo_wine
ok(hr == S_OK, "Waiting for event failed, hr %#x.\n", hr);
is_debugged = TRUE;
ret = CheckRemoteDebuggerPresent(info.hProcess, &is_debugged);
ok(ret, "Failed to check target status.\n");
ok(!is_debugged, "Unexpected mode.\n");
hr = client->lpVtbl->DetachProcesses(client);
todo_wine
ok(hr == S_OK, "Failed to detach, hr %#x.\n", hr);
hr = client->lpVtbl->EndSession(client, DEBUG_END_ACTIVE_DETACH);
todo_wine
ok(hr == S_OK, "Failed to end session, hr %#x.\n", hr);
SetEvent(event);
winetest_wait_child_process(info.hProcess);
CloseHandle(info.hProcess);
CloseHandle(info.hThread);
CloseHandle(event);
client->lpVtbl->Release(client);
control->lpVtbl->Release(control);
}
static void target_proc(void)
{
HANDLE event = OpenEventA(SYNCHRONIZE, FALSE, event_name);
ok(event != NULL, "Failed to open event handle.\n");
for (;;)
{
if (WaitForSingleObject(event, 100) == WAIT_OBJECT_0)
break;
}
CloseHandle(event);
}
START_TEST(dbgeng)
{
char **argv;
int argc;
argc = winetest_get_mainargs(&argv);
if (argc >= 3 && !strcmp(argv[2], "target"))
{
target_proc();
return;
}
test_engine_options();
test_attach();
}
......@@ -73,6 +73,95 @@ DEFINE_GUID(IID_IDebugSystemObjects3, 0xe9676e2f, 0xe286, 0x4ea3, 0xb0, 0xf9
#define DEBUG_ATTACH_INVASIVE_RESUME_PROCESS 0x00000010
#define DEBUG_ATTACH_NONINVASIVE_ALLOW_PARTIAL 0x00000020
/* EndSession() flags */
#define DEBUG_END_PASSIVE 0x00000000
#define DEBUG_END_ACTIVE_TERMINATE 0x00000001
#define DEBUG_END_ACTIVE_DETACH 0x00000002
#define DEBUG_END_REENTRANT 0x00000003
#define DEBUG_END_DISCONNECT 0x00000004
/* ChangeEngineState() flags */
#define DEBUG_CES_CURRENT_THREAD 0x00000001
#define DEBUG_CES_EFFECTIVE_PROCESSOR 0x00000002
#define DEBUG_CES_BREAKPOINTS 0x00000004
#define DEBUG_CES_CODE_LEVEL 0x00000008
#define DEBUG_CES_EXECUTION_STATUS 0x00000010
#define DEBUG_CES_ENGINE_OPTIONS 0x00000020
#define DEBUG_CES_LOG_FILE 0x00000040
#define DEBUG_CES_RADIX 0x00000080
#define DEBUG_CES_EVENT_FILTERS 0x00000100
#define DEBUG_CES_PROCESS_OPTIONS 0x00000200
#define DEBUG_CES_EXTENSIONS 0x00000400
#define DEBUG_CES_SYSTEMS 0x00000800
#define DEBUG_CES_ASSEMBLY_OPTIONS 0x00001000
#define DEBUG_CES_EXPRESSION_SYNTAX 0x00002000
#define DEBUG_CES_TEXT_REPLACEMENTS 0x00004000
#define DEBUG_CES_ALL 0xffffffff
#define DEBUG_STATUS_NO_CHANGE 0
#define DEBUG_STATUS_GO 1
#define DEBUG_STATUS_GO_HANDLED 2
#define DEBUG_STATUS_GO_NOT_HANDLED 3
#define DEBUG_STATUS_STEP_OVER 4
#define DEBUG_STATUS_STEP_INTO 5
#define DEBUG_STATUS_BREAK 6
#define DEBUG_STATUS_NO_DEBUGGEE 7
#define DEBUG_STATUS_STEP_BRANCH 8
#define DEBUG_STATUS_IGNORE_EVENT 9
#define DEBUG_STATUS_RESTART_REQUESTED 10
#define DEBUG_STATUS_REVERSE_GO 11
#define DEBUG_STATUS_REVERSE_STEP_BRANCH 12
#define DEBUG_STATUS_REVERSE_STEP_OVER 13
#define DEBUG_STATUS_REVERSE_STEP_INTO 14
#define DEBUG_STATUS_OUT_OF_SYNC 15
#define DEBUG_STATUS_WAIT_INPUT 16
#define DEBUG_STATUS_TIMEOUT 17
#define DEBUG_STATUS_MASK 0x1f
/* ChangeSymbolState() flags */
#define DEBUG_CSS_LOADS 0x00000001
#define DEBUG_CSS_UNLOADS 0x00000002
#define DEBUG_CSS_SCOPE 0x00000004
#define DEBUG_CSS_PATHS 0x00000008
#define DEBUG_CSS_SYMBOL_OPTIONS 0x00000010
#define DEBUG_CSS_TYPE_OPTIONS 0x00000020
#define DEBUG_CSS_COLLAPSE_CHILDREN 0x00000040
#define DEBUG_CSS_ALL 0xffffffff
/* SessionStatus() flags */
#define DEBUG_SESSION_ACTIVE 0x00000000
#define DEBUG_SESSION_END_SESSION_ACTIVE_TERMINATE 0x00000001
#define DEBUG_SESSION_END_SESSION_ACTIVE_DETACH 0x00000002
#define DEBUG_SESSION_END_SESSION_PASSIVE 0x00000003
#define DEBUG_SESSION_END 0x00000004
#define DEBUG_SESSION_REBOOT 0x00000005
#define DEBUG_SESSION_HIBERNATE 0x00000006
#define DEBUG_SESSION_FAILURE 0x00000007
/* ChangeDebuggeeState() flags */
#define DEBUG_CDS_REGISTERS 0x00000001
#define DEBUG_CDS_DATA 0x00000002
#define DEBUG_CDS_REFRESH 0x00000004
#define DEBUG_CDS_ALL 0xffffffff
#define DEBUG_CDS_REFRESH_EVALUATE 1
#define DEBUG_CDS_REFRESH_EXECUTE 2
#define DEBUG_CDS_REFRESH_EXECUTECOMMANDFILE 3
#define DEBUG_CDS_REFRESH_ADDBREAKPOINT 4
#define DEBUG_CDS_REFRESH_REMOVEBREAKPOINT 5
#define DEBUG_CDS_REFRESH_WRITEVIRTUAL 6
#define DEBUG_CDS_REFRESH_WRITEVIRTUALUNCACHED 7
#define DEBUG_CDS_REFRESH_WRITEPHYSICAL 8
#define DEBUG_CDS_REFRESH_WRITEPHYSICAL2 9
#define DEBUG_CDS_REFRESH_SETVALUE 10
#define DEBUG_CDS_REFRESH_SETVALUE2 11
#define DEBUG_CDS_REFRESH_SETSCOPE 12
#define DEBUG_CDS_REFRESH_SETSCOPEFRAMEBYINDEX 13
#define DEBUG_CDS_REFRESH_SETSCOPEFROMJITDEBUGINFO 14
#define DEBUG_CDS_REFRESH_SETSCOPEFROMSTOREDEVENT 15
#define DEBUG_CDS_REFRESH_INLINESTEP 16
#define DEBUG_CDS_REFRESH_INLINESTEP_PSEUDO 17
typedef struct _DEBUG_MODULE_PARAMETERS
{
ULONG64 Base;
......
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