Commit 4557a007 authored by Nikolay Sivov's avatar Nikolay Sivov Committed by Alexandre Julliard

dbgeng: Add support for non-invasive attach on WaitForEvent().

parent c5584f5f
...@@ -35,11 +35,15 @@ ...@@ -35,11 +35,15 @@
WINE_DEFAULT_DEBUG_CHANNEL(dbgeng); WINE_DEFAULT_DEBUG_CHANNEL(dbgeng);
extern NTSTATUS WINAPI NtSuspendProcess(HANDLE handle);
extern NTSTATUS WINAPI NtResumeProcess(HANDLE handle);
struct target_process struct target_process
{ {
struct list entry; struct list entry;
unsigned int pid; unsigned int pid;
unsigned int attach_flags; unsigned int attach_flags;
HANDLE handle;
}; };
struct debug_client struct debug_client
...@@ -54,6 +58,28 @@ struct debug_client ...@@ -54,6 +58,28 @@ struct debug_client
IDebugEventCallbacks *event_callbacks; IDebugEventCallbacks *event_callbacks;
}; };
static void debug_client_detach_target(struct target_process *target)
{
NTSTATUS status;
if (!target->handle)
return;
if (target->attach_flags & DEBUG_ATTACH_NONINVASIVE)
{
BOOL resume = !(target->attach_flags & DEBUG_ATTACH_NONINVASIVE_NO_SUSPEND);
if (resume)
{
if ((status = NtResumeProcess(target->handle)))
WARN("Failed to resume process, status %#x.\n", status);
}
}
CloseHandle(target->handle);
target->handle = NULL;
}
static struct debug_client *impl_from_IDebugClient(IDebugClient *iface) static struct debug_client *impl_from_IDebugClient(IDebugClient *iface)
{ {
return CONTAINING_RECORD(iface, struct debug_client, IDebugClient_iface); return CONTAINING_RECORD(iface, struct debug_client, IDebugClient_iface);
...@@ -133,6 +159,7 @@ static ULONG STDMETHODCALLTYPE debugclient_Release(IDebugClient *iface) ...@@ -133,6 +159,7 @@ static ULONG STDMETHODCALLTYPE debugclient_Release(IDebugClient *iface)
{ {
LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &debug_client->targets, struct target_process, entry) LIST_FOR_EACH_ENTRY_SAFE(cur, cur2, &debug_client->targets, struct target_process, entry)
{ {
debug_client_detach_target(cur);
list_remove(&cur->entry); list_remove(&cur->entry);
heap_free(cur); heap_free(cur);
} }
...@@ -329,9 +356,17 @@ static HRESULT STDMETHODCALLTYPE debugclient_TerminateProcesses(IDebugClient *if ...@@ -329,9 +356,17 @@ static HRESULT STDMETHODCALLTYPE debugclient_TerminateProcesses(IDebugClient *if
static HRESULT STDMETHODCALLTYPE debugclient_DetachProcesses(IDebugClient *iface) static HRESULT STDMETHODCALLTYPE debugclient_DetachProcesses(IDebugClient *iface)
{ {
FIXME("%p stub.\n", iface); struct debug_client *debug_client = impl_from_IDebugClient(iface);
struct target_process *target;
return E_NOTIMPL; TRACE("%p.\n", iface);
LIST_FOR_EACH_ENTRY(target, &debug_client->targets, struct target_process, entry)
{
debug_client_detach_target(target);
}
return S_OK;
} }
static HRESULT STDMETHODCALLTYPE debugclient_EndSession(IDebugClient *iface, ULONG flags) static HRESULT STDMETHODCALLTYPE debugclient_EndSession(IDebugClient *iface, ULONG flags)
...@@ -2637,7 +2672,47 @@ static HRESULT STDMETHODCALLTYPE debugcontrol_SetExceptionFilterSecondCommand(ID ...@@ -2637,7 +2672,47 @@ static HRESULT STDMETHODCALLTYPE debugcontrol_SetExceptionFilterSecondCommand(ID
static HRESULT STDMETHODCALLTYPE debugcontrol_WaitForEvent(IDebugControl2 *iface, ULONG flags, ULONG timeout) static HRESULT STDMETHODCALLTYPE debugcontrol_WaitForEvent(IDebugControl2 *iface, ULONG flags, ULONG timeout)
{ {
FIXME("%p, %#x, %u stub.\n", iface, flags, timeout); struct debug_client *debug_client = impl_from_IDebugControl2(iface);
struct target_process *target;
TRACE("%p, %#x, %u.\n", iface, flags, timeout);
/* FIXME: only one target is used currently */
if (list_empty(&debug_client->targets))
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;
NTSTATUS status;
if (suspend)
access |= PROCESS_SUSPEND_RESUME;
target->handle = OpenProcess(access, FALSE, target->pid);
if (!target->handle)
{
WARN("Failed to get process handle for pid %#x.\n", target->pid);
return E_UNEXPECTED;
}
if (suspend)
{
status = NtSuspendProcess(target->handle);
if (status)
WARN("Failed to suspend a process, status %#x.\n", status);
}
return S_OK;
}
else
{
FIXME("Unsupported attach flags %#x.\n", target->attach_flags);
}
return E_NOTIMPL; return E_NOTIMPL;
} }
......
...@@ -273,7 +273,6 @@ static void test_attach(void) ...@@ -273,7 +273,6 @@ static void test_attach(void)
ok(!is_debugged, "Unexpected mode.\n"); ok(!is_debugged, "Unexpected mode.\n");
hr = control->lpVtbl->WaitForEvent(control, 0, INFINITE); hr = control->lpVtbl->WaitForEvent(control, 0, INFINITE);
todo_wine
ok(hr == S_OK, "Waiting for event failed, hr %#x.\n", hr); ok(hr == S_OK, "Waiting for event failed, hr %#x.\n", hr);
is_debugged = TRUE; is_debugged = TRUE;
...@@ -282,7 +281,6 @@ todo_wine ...@@ -282,7 +281,6 @@ todo_wine
ok(!is_debugged, "Unexpected mode.\n"); ok(!is_debugged, "Unexpected mode.\n");
hr = client->lpVtbl->DetachProcesses(client); hr = client->lpVtbl->DetachProcesses(client);
todo_wine
ok(hr == S_OK, "Failed to detach, hr %#x.\n", hr); ok(hr == S_OK, "Failed to detach, hr %#x.\n", hr);
hr = client->lpVtbl->EndSession(client, DEBUG_END_ACTIVE_DETACH); hr = client->lpVtbl->EndSession(client, DEBUG_END_ACTIVE_DETACH);
......
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