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