Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/dbgeng/dbgeng.c | 81 ++++++++++++++++++++++++++++++++++++-- dlls/dbgeng/tests/dbgeng.c | 2 - 2 files changed, 78 insertions(+), 5 deletions(-)
diff --git a/dlls/dbgeng/dbgeng.c b/dlls/dbgeng/dbgeng.c index c54d13f6cd..8ce7ac656a 100644 --- a/dlls/dbgeng/dbgeng.c +++ b/dlls/dbgeng/dbgeng.c @@ -35,11 +35,15 @@
WINE_DEFAULT_DEBUG_CHANNEL(dbgeng);
+extern NTSTATUS WINAPI NtSuspendProcess(HANDLE handle); +extern NTSTATUS WINAPI NtResumeProcess(HANDLE handle); + struct target_process { struct list entry; unsigned int pid; unsigned int attach_flags; + HANDLE handle; };
struct debug_client @@ -54,6 +58,28 @@ struct debug_client 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) { return CONTAINING_RECORD(iface, struct debug_client, 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) { + debug_client_detach_target(cur); list_remove(&cur->entry); heap_free(cur); } @@ -329,9 +356,17 @@ static HRESULT STDMETHODCALLTYPE debugclient_TerminateProcesses(IDebugClient *if
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) @@ -2637,7 +2672,47 @@ static HRESULT STDMETHODCALLTYPE debugcontrol_SetExceptionFilterSecondCommand(ID
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; } diff --git a/dlls/dbgeng/tests/dbgeng.c b/dlls/dbgeng/tests/dbgeng.c index baec60a9c9..650ab4abae 100644 --- a/dlls/dbgeng/tests/dbgeng.c +++ b/dlls/dbgeng/tests/dbgeng.c @@ -273,7 +273,6 @@ static void test_attach(void) 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; @@ -282,7 +281,6 @@ todo_wine 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);