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

Signed-off-by: Nikolay Sivov <nsivov@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
stable
Nikolay Sivov 2019-04-22 09:42:25 +03:00 committed by Alexandre Julliard
parent c5584f5ff1
commit 4557a007d7
2 changed files with 78 additions and 5 deletions

View File

@ -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;
}

View File

@ -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);