Nikolay Sivov : dbgeng: Add support for non-invasive attach on WaitForEvent().
Alexandre Julliard
julliard at winehq.org
Mon Apr 22 16:30:38 CDT 2019
Module: wine
Branch: master
Commit: 4557a007d70cac23e76d7e444a6dcfbf5e02349b
URL: https://source.winehq.org/git/wine.git/?a=commit;h=4557a007d70cac23e76d7e444a6dcfbf5e02349b
Author: Nikolay Sivov <nsivov at codeweavers.com>
Date: Mon Apr 22 09:42:25 2019 +0300
dbgeng: Add support for non-invasive attach on WaitForEvent().
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
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 c54d13f..8ce7ac6 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 baec60a..650ab4a 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);
More information about the wine-cvs
mailing list