ntdll: Implement NtDebugActiveProcess() and NtRemoveProcessDebug().
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
11e6f1007c
commit
46b84e7a83
|
@ -91,22 +91,15 @@ BOOL WINAPI DECLSPEC_HOTPATCH ContinueDebugEvent( DWORD pid, DWORD tid, DWORD st
|
|||
BOOL WINAPI DECLSPEC_HOTPATCH DebugActiveProcess( DWORD pid )
|
||||
{
|
||||
HANDLE process;
|
||||
BOOL ret;
|
||||
NTSTATUS status;
|
||||
|
||||
SERVER_START_REQ( debug_process )
|
||||
{
|
||||
req->pid = pid;
|
||||
req->attach = 1;
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (!ret) return FALSE;
|
||||
|
||||
if (!(process = OpenProcess( PROCESS_CREATE_THREAD, FALSE, pid ))) return FALSE;
|
||||
ret = set_ntstatus( DbgUiIssueRemoteBreakin( process ));
|
||||
if (!set_ntstatus( DbgUiConnectToDbg() )) return FALSE;
|
||||
if (!(process = OpenProcess( PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_SUSPEND_RESUME |
|
||||
PROCESS_CREATE_THREAD, FALSE, pid )))
|
||||
return FALSE;
|
||||
status = DbgUiDebugActiveProcess( process );
|
||||
NtClose( process );
|
||||
if (!ret) DebugActiveProcessStop( pid );
|
||||
return ret;
|
||||
return set_ntstatus( status );
|
||||
}
|
||||
|
||||
|
||||
|
@ -115,16 +108,14 @@ BOOL WINAPI DECLSPEC_HOTPATCH DebugActiveProcess( DWORD pid )
|
|||
*/
|
||||
BOOL WINAPI DECLSPEC_HOTPATCH DebugActiveProcessStop( DWORD pid )
|
||||
{
|
||||
BOOL ret;
|
||||
HANDLE process;
|
||||
NTSTATUS status;
|
||||
|
||||
SERVER_START_REQ( debug_process )
|
||||
{
|
||||
req->pid = pid;
|
||||
req->attach = 0;
|
||||
ret = !wine_server_call_err( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
if (!(process = OpenProcess( PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_SUSPEND_RESUME, FALSE, pid )))
|
||||
return FALSE;
|
||||
status = DbgUiStopDebugging( process );
|
||||
NtClose( process );
|
||||
return set_ntstatus( status );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -37,12 +37,12 @@
|
|||
@ stdcall DbgUiConnectToDbg()
|
||||
@ stub DbgUiContinue
|
||||
@ stub DbgUiConvertStateChangeStructure
|
||||
# @ stub DbgUiDebugActiveProcess
|
||||
@ stdcall DbgUiDebugActiveProcess(long)
|
||||
@ stdcall DbgUiGetThreadDebugObject()
|
||||
@ stdcall DbgUiIssueRemoteBreakin(long)
|
||||
@ stdcall DbgUiRemoteBreakin(ptr)
|
||||
@ stdcall DbgUiSetThreadDebugObject(long)
|
||||
# @ stub DbgUiStopDebugging
|
||||
@ stdcall DbgUiStopDebugging(long)
|
||||
@ stub DbgUiWaitStateChange
|
||||
@ stdcall DbgUserBreakPoint()
|
||||
@ stdcall EtwEventActivityIdControl(long ptr)
|
||||
|
@ -340,7 +340,7 @@
|
|||
@ stdcall -syscall NtReleaseSemaphore(long long ptr)
|
||||
@ stdcall -syscall NtRemoveIoCompletion(ptr ptr ptr ptr ptr)
|
||||
@ stdcall -syscall NtRemoveIoCompletionEx(ptr ptr long ptr ptr long)
|
||||
# @ stub NtRemoveProcessDebug
|
||||
@ stdcall -syscall NtRemoveProcessDebug(long long)
|
||||
@ stdcall -syscall NtRenameKey(long ptr)
|
||||
@ stdcall -syscall NtReplaceKey(ptr long ptr)
|
||||
@ stub NtReplyPort
|
||||
|
@ -1345,7 +1345,7 @@
|
|||
@ stdcall -private -syscall ZwReleaseSemaphore(long long ptr) NtReleaseSemaphore
|
||||
@ stdcall -private -syscall ZwRemoveIoCompletion(ptr ptr ptr ptr ptr) NtRemoveIoCompletion
|
||||
@ stdcall -private -syscall ZwRemoveIoCompletionEx(ptr ptr long ptr ptr long) NtRemoveIoCompletionEx
|
||||
# @ stub ZwRemoveProcessDebug
|
||||
@ stdcall -private -syscall ZwRemoveProcessDebug(long long) NtRemoveProcessDebug
|
||||
@ stdcall -private -syscall ZwRenameKey(long ptr) NtRenameKey
|
||||
@ stdcall -private -syscall ZwReplaceKey(ptr long ptr) NtReplaceKey
|
||||
@ stub ZwReplyPort
|
||||
|
|
|
@ -150,6 +150,26 @@ NTSTATUS WINAPI DbgUiConnectToDbg(void)
|
|||
return status;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* DbgUiDebugActiveProcess (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI DbgUiDebugActiveProcess( HANDLE process )
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
if ((status = NtDebugActiveProcess( process, DbgUiGetThreadDebugObject() ))) return status;
|
||||
if ((status = DbgUiIssueRemoteBreakin( process ))) DbgUiStopDebugging( process );
|
||||
return status;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* DbgUiStopDebugging (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI DbgUiStopDebugging( HANDLE process )
|
||||
{
|
||||
return NtRemoveProcessDebug( process, DbgUiGetThreadDebugObject() );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* DbgUiRemoteBreakin (NTDLL.@)
|
||||
*/
|
||||
|
|
|
@ -1746,10 +1746,38 @@ NTSTATUS WINAPI NtResumeProcess( HANDLE handle )
|
|||
/**********************************************************************
|
||||
* NtDebugActiveProcess (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI NtDebugActiveProcess( HANDLE process, HANDLE debug_object )
|
||||
NTSTATUS WINAPI NtDebugActiveProcess( HANDLE process, HANDLE debug )
|
||||
{
|
||||
FIXME( "(%p %p), stub!\n", process, debug_object );
|
||||
return STATUS_SUCCESS;
|
||||
NTSTATUS ret;
|
||||
|
||||
SERVER_START_REQ( debug_process )
|
||||
{
|
||||
req->handle = wine_server_obj_handle( process );
|
||||
req->debug = wine_server_obj_handle( debug );
|
||||
req->attach = 1;
|
||||
ret = wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NtRemoveProcessDebug (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI NtRemoveProcessDebug( HANDLE process, HANDLE debug )
|
||||
{
|
||||
NTSTATUS ret;
|
||||
|
||||
SERVER_START_REQ( debug_process )
|
||||
{
|
||||
req->handle = wine_server_obj_handle( process );
|
||||
req->debug = wine_server_obj_handle( debug );
|
||||
req->attach = 0;
|
||||
ret = wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -2094,9 +2094,9 @@ struct continue_debug_event_reply
|
|||
struct debug_process_request
|
||||
{
|
||||
struct request_header __header;
|
||||
process_id_t pid;
|
||||
obj_handle_t handle;
|
||||
obj_handle_t debug;
|
||||
int attach;
|
||||
char __pad_20[4];
|
||||
};
|
||||
struct debug_process_reply
|
||||
{
|
||||
|
@ -6211,7 +6211,7 @@ union generic_reply
|
|||
|
||||
/* ### protocol_version begin ### */
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 658
|
||||
#define SERVER_PROTOCOL_VERSION 659
|
||||
|
||||
/* ### protocol_version end ### */
|
||||
|
||||
|
|
|
@ -3023,10 +3023,12 @@ NTSYSAPI void WINAPI DbgBreakPoint(void);
|
|||
NTSYSAPI NTSTATUS WINAPIV DbgPrint(LPCSTR fmt, ...);
|
||||
NTSYSAPI NTSTATUS WINAPIV DbgPrintEx(ULONG iComponentId, ULONG Level, LPCSTR fmt, ...);
|
||||
NTSYSAPI NTSTATUS WINAPI DbgUiConnectToDbg(void);
|
||||
NTSYSAPI NTSTATUS WINAPI DbgUiDebugActiveProcess(HANDLE);
|
||||
NTSYSAPI HANDLE WINAPI DbgUiGetThreadDebugObject(void);
|
||||
NTSYSAPI NTSTATUS WINAPI DbgUiIssueRemoteBreakin(HANDLE);
|
||||
NTSYSAPI void WINAPI DbgUiRemoteBreakin(void*);
|
||||
NTSYSAPI void WINAPI DbgUiSetThreadDebugObject(HANDLE);
|
||||
NTSYSAPI NTSTATUS WINAPI DbgUiStopDebugging(HANDLE);
|
||||
NTSYSAPI void WINAPI DbgUserBreakPoint(void);
|
||||
NTSYSAPI NTSTATUS WINAPI LdrAccessResource(HMODULE,const IMAGE_RESOURCE_DATA_ENTRY*,void**,PULONG);
|
||||
NTSYSAPI NTSTATUS WINAPI LdrAddDllDirectory(const UNICODE_STRING*,void**);
|
||||
|
@ -3104,6 +3106,7 @@ NTSYSAPI NTSTATUS WINAPI NtCreateThreadEx(HANDLE*,ACCESS_MASK,OBJECT_ATTRIBUTES
|
|||
NTSYSAPI NTSTATUS WINAPI NtCreateTimer(HANDLE*, ACCESS_MASK, const OBJECT_ATTRIBUTES*, TIMER_TYPE);
|
||||
NTSYSAPI NTSTATUS WINAPI NtCreateToken(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,TOKEN_TYPE,PLUID,PLARGE_INTEGER,PTOKEN_USER,PTOKEN_GROUPS,PTOKEN_PRIVILEGES,PTOKEN_OWNER,PTOKEN_PRIMARY_GROUP,PTOKEN_DEFAULT_DACL,PTOKEN_SOURCE);
|
||||
NTSYSAPI NTSTATUS WINAPI NtCreateUserProcess(HANDLE*,HANDLE*,ACCESS_MASK,ACCESS_MASK,OBJECT_ATTRIBUTES*,OBJECT_ATTRIBUTES*,ULONG,ULONG,RTL_USER_PROCESS_PARAMETERS*,PS_CREATE_INFO*,PS_ATTRIBUTE_LIST*);
|
||||
NTSYSAPI NTSTATUS WINAPI NtDebugActiveProcess(HANDLE,HANDLE);
|
||||
NTSYSAPI NTSTATUS WINAPI NtDelayExecution(BOOLEAN,const LARGE_INTEGER*);
|
||||
NTSYSAPI NTSTATUS WINAPI NtDeleteAtom(RTL_ATOM);
|
||||
NTSYSAPI NTSTATUS WINAPI NtDeleteFile(POBJECT_ATTRIBUTES);
|
||||
|
@ -3228,6 +3231,7 @@ NTSYSAPI NTSTATUS WINAPI NtReleaseMutant(HANDLE,PLONG);
|
|||
NTSYSAPI NTSTATUS WINAPI NtReleaseSemaphore(HANDLE,ULONG,PULONG);
|
||||
NTSYSAPI NTSTATUS WINAPI NtRemoveIoCompletion(HANDLE,PULONG_PTR,PULONG_PTR,PIO_STATUS_BLOCK,PLARGE_INTEGER);
|
||||
NTSYSAPI NTSTATUS WINAPI NtRemoveIoCompletionEx(HANDLE,FILE_IO_COMPLETION_INFORMATION*,ULONG,ULONG*,LARGE_INTEGER*,BOOLEAN);
|
||||
NTSYSAPI NTSTATUS WINAPI NtRemoveProcessDebug(HANDLE,HANDLE);
|
||||
NTSYSAPI NTSTATUS WINAPI NtRenameKey(HANDLE,UNICODE_STRING*);
|
||||
NTSYSAPI NTSTATUS WINAPI NtReplaceKey(POBJECT_ATTRIBUTES,HANDLE,POBJECT_ATTRIBUTES);
|
||||
NTSYSAPI NTSTATUS WINAPI NtReplyPort(HANDLE,PLPC_MESSAGE);
|
||||
|
|
|
@ -485,34 +485,30 @@ void resume_delayed_debug_events( struct thread *thread )
|
|||
}
|
||||
|
||||
/* attach a process to a debugger thread and suspend it */
|
||||
static int debugger_attach( struct process *process, struct thread *debugger )
|
||||
static int debugger_attach( struct process *process, struct thread *debugger, struct debug_obj *debug_obj )
|
||||
{
|
||||
if (process->debug_obj) goto error; /* already being debugged */
|
||||
if (debugger->process == process) goto error;
|
||||
if (!is_process_init_done( process )) goto error; /* still starting up */
|
||||
if (list_empty( &process->thread_list )) goto error; /* no thread running in the process */
|
||||
|
||||
/* don't let a debugger debug its console... won't work */
|
||||
if (debugger->process->console)
|
||||
{
|
||||
struct thread *renderer = console_get_renderer(debugger->process->console);
|
||||
if (renderer && renderer->process == process)
|
||||
goto error;
|
||||
if (renderer && renderer->process == process) goto error;
|
||||
}
|
||||
if (!debugger->debug_obj) debugger->debug_obj = (struct debug_obj *)grab_object( debug_obj );
|
||||
|
||||
suspend_process( process );
|
||||
if (!set_process_debugger( process, debugger ))
|
||||
{
|
||||
resume_process( process );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!set_process_debug_flag( process, 1 ))
|
||||
{
|
||||
process->debug_obj = NULL;
|
||||
resume_process( process );
|
||||
return 0;
|
||||
}
|
||||
process->debug_obj = debug_obj;
|
||||
process->debug_children = 0;
|
||||
generate_startup_debug_events( process, 0 );
|
||||
resume_process( process );
|
||||
return 1;
|
||||
|
||||
error:
|
||||
|
@ -526,9 +522,6 @@ void debugger_detach( struct process *process, struct debug_obj *debug_obj )
|
|||
{
|
||||
struct debug_event *event, *next;
|
||||
|
||||
/* init should be done, otherwise wouldn't be attached */
|
||||
assert(is_process_init_done(process));
|
||||
|
||||
suspend_process( process );
|
||||
|
||||
/* send continue indication for all events */
|
||||
|
@ -549,7 +542,6 @@ void debugger_detach( struct process *process, struct debug_obj *debug_obj )
|
|||
process->debug_obj = NULL;
|
||||
if (!set_process_debug_flag( process, 0 )) clear_error(); /* ignore error */
|
||||
|
||||
/* from this function */
|
||||
resume_process( process );
|
||||
}
|
||||
|
||||
|
@ -584,22 +576,6 @@ void generate_startup_debug_events( struct process *process, client_ptr_t entry
|
|||
}
|
||||
}
|
||||
|
||||
/* set the debugger of a given process */
|
||||
int set_process_debugger( struct process *process, struct thread *debugger )
|
||||
{
|
||||
struct debug_obj *debug_obj;
|
||||
|
||||
assert( !process->debug_obj );
|
||||
|
||||
if (!debugger->debug_obj) /* need to allocate a context */
|
||||
{
|
||||
if (!(debug_obj = create_debug_obj( NULL, NULL, 0, DEBUG_KILL_ON_CLOSE, NULL ))) return 0;
|
||||
debugger->debug_obj = debug_obj;
|
||||
}
|
||||
process->debug_obj = debugger->debug_obj;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* a thread is exiting */
|
||||
void debug_exit_thread( struct thread *thread )
|
||||
{
|
||||
|
@ -692,23 +668,27 @@ DECL_HANDLER(continue_debug_event)
|
|||
}
|
||||
}
|
||||
|
||||
/* Start debugging an existing process */
|
||||
/* start or stop debugging an existing process */
|
||||
DECL_HANDLER(debug_process)
|
||||
{
|
||||
struct process *process = get_process_from_id( req->pid );
|
||||
if (!process) return;
|
||||
struct debug_obj *debug_obj;
|
||||
struct process *process = get_process_from_handle( req->handle,
|
||||
PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_SUSPEND_RESUME );
|
||||
|
||||
if (!req->attach)
|
||||
if (!process) return;
|
||||
if ((debug_obj = get_debug_obj( current->process, req->debug, DEBUG_PROCESS_ASSIGN )))
|
||||
{
|
||||
if (current->debug_obj && process->debug_obj == current->debug_obj)
|
||||
debugger_detach( process, current->debug_obj );
|
||||
else
|
||||
set_error( STATUS_ACCESS_DENIED );
|
||||
if (req->attach)
|
||||
{
|
||||
if (!process->debug_obj) debugger_attach( process, current, debug_obj );
|
||||
else set_error( STATUS_ACCESS_DENIED );
|
||||
}
|
||||
else if (debugger_attach( process, current ))
|
||||
else
|
||||
{
|
||||
generate_startup_debug_events( process, 0 );
|
||||
resume_process( process );
|
||||
if (process->debug_obj == debug_obj) debugger_detach( process, debug_obj );
|
||||
else set_error( STATUS_ACCESS_DENIED );
|
||||
}
|
||||
release_object( debug_obj );
|
||||
}
|
||||
release_object( process );
|
||||
}
|
||||
|
|
|
@ -212,7 +212,6 @@ extern void sock_init(void);
|
|||
|
||||
/* debugger functions */
|
||||
|
||||
extern int set_process_debugger( struct process *process, struct thread *debugger );
|
||||
extern void generate_debug_event( struct thread *thread, int code, const void *arg );
|
||||
extern void resume_delayed_debug_events( struct thread *thread );
|
||||
extern void generate_startup_debug_events( struct process *process, client_ptr_t entry );
|
||||
|
|
|
@ -1637,9 +1637,10 @@ struct process_info
|
|||
@END
|
||||
|
||||
|
||||
/* Start/stop debugging an existing process */
|
||||
/* Start or stop debugging an existing process */
|
||||
@REQ(debug_process)
|
||||
process_id_t pid; /* id of the process to debug */
|
||||
obj_handle_t handle; /* process handle */
|
||||
obj_handle_t debug; /* debug object to attach to the process */
|
||||
int attach; /* 1=attaching / 0=detaching from the process */
|
||||
@END
|
||||
|
||||
|
|
|
@ -1159,8 +1159,9 @@ C_ASSERT( FIELD_OFFSET(struct continue_debug_event_request, pid) == 12 );
|
|||
C_ASSERT( FIELD_OFFSET(struct continue_debug_event_request, tid) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct continue_debug_event_request, status) == 20 );
|
||||
C_ASSERT( sizeof(struct continue_debug_event_request) == 24 );
|
||||
C_ASSERT( FIELD_OFFSET(struct debug_process_request, pid) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct debug_process_request, attach) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct debug_process_request, handle) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct debug_process_request, debug) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct debug_process_request, attach) == 20 );
|
||||
C_ASSERT( sizeof(struct debug_process_request) == 24 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_debugger_kill_on_exit_request, kill_on_exit) == 12 );
|
||||
C_ASSERT( sizeof(struct set_debugger_kill_on_exit_request) == 16 );
|
||||
|
|
|
@ -2206,7 +2206,8 @@ static void dump_continue_debug_event_request( const struct continue_debug_event
|
|||
|
||||
static void dump_debug_process_request( const struct debug_process_request *req )
|
||||
{
|
||||
fprintf( stderr, " pid=%04x", req->pid );
|
||||
fprintf( stderr, " handle=%04x", req->handle );
|
||||
fprintf( stderr, ", debug=%04x", req->debug );
|
||||
fprintf( stderr, ", attach=%d", req->attach );
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue