server: Implement retrieving the debug object of a process.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
988dc7753a
commit
52d733b5c4
|
@ -1813,12 +1813,12 @@ static void test_query_process_debug_object_handle(int argc, char **argv)
|
||||||
debug_object = (HANDLE)0xdeadbeef;
|
debug_object = (HANDLE)0xdeadbeef;
|
||||||
status = pNtQueryInformationProcess(pi.hProcess, ProcessDebugObjectHandle,
|
status = pNtQueryInformationProcess(pi.hProcess, ProcessDebugObjectHandle,
|
||||||
&debug_object, sizeof(debug_object), NULL);
|
&debug_object, sizeof(debug_object), NULL);
|
||||||
todo_wine
|
|
||||||
ok(status == STATUS_SUCCESS,
|
ok(status == STATUS_SUCCESS,
|
||||||
"Expected NtQueryInformationProcess to return STATUS_SUCCESS, got 0x%08x\n", status);
|
"Expected NtQueryInformationProcess to return STATUS_SUCCESS, got 0x%08x\n", status);
|
||||||
todo_wine
|
|
||||||
ok(debug_object != NULL,
|
ok(debug_object != NULL,
|
||||||
"Expected debug object handle to be non-NULL, got %p\n", debug_object);
|
"Expected debug object handle to be non-NULL, got %p\n", debug_object);
|
||||||
|
status = NtClose( debug_object );
|
||||||
|
ok( !status, "NtClose failed %x\n", status );
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1366,15 +1366,25 @@ NTSTATUS WINAPI NtQueryInformationProcess( HANDLE handle, PROCESSINFOCLASS class
|
||||||
if (!info) ret = STATUS_ACCESS_VIOLATION;
|
if (!info) ret = STATUS_ACCESS_VIOLATION;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SERVER_START_REQ(get_process_info)
|
HANDLE debug;
|
||||||
|
|
||||||
|
SERVER_START_REQ(get_process_debug_info)
|
||||||
{
|
{
|
||||||
req->handle = wine_server_obj_handle( handle );
|
req->handle = wine_server_obj_handle( handle );
|
||||||
if ((ret = wine_server_call( req )) == STATUS_SUCCESS)
|
ret = wine_server_call( req );
|
||||||
{
|
debug = wine_server_ptr_handle( reply->debug );
|
||||||
*(DWORD_PTR *)info = reply->debugger_present ? ~(DWORD_PTR)0 : 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
|
if (ret == STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
*(DWORD_PTR *)info = ~0ul;
|
||||||
|
NtClose( debug );
|
||||||
|
}
|
||||||
|
else if (ret == STATUS_PORT_NOT_SET)
|
||||||
|
{
|
||||||
|
*(DWORD_PTR *)info = 0;
|
||||||
|
ret = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else ret = STATUS_INFO_LENGTH_MISMATCH;
|
else ret = STATUS_INFO_LENGTH_MISMATCH;
|
||||||
|
@ -1387,15 +1397,18 @@ NTSTATUS WINAPI NtQueryInformationProcess( HANDLE handle, PROCESSINFOCLASS class
|
||||||
if (!info) ret = STATUS_ACCESS_VIOLATION;
|
if (!info) ret = STATUS_ACCESS_VIOLATION;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
SERVER_START_REQ(get_process_info)
|
HANDLE debug;
|
||||||
|
|
||||||
|
SERVER_START_REQ(get_process_debug_info)
|
||||||
{
|
{
|
||||||
req->handle = wine_server_obj_handle( handle );
|
req->handle = wine_server_obj_handle( handle );
|
||||||
if ((ret = wine_server_call( req )) == STATUS_SUCCESS)
|
ret = wine_server_call( req );
|
||||||
{
|
debug = wine_server_ptr_handle( reply->debug );
|
||||||
*(DWORD *)info = reply->debug_children;
|
*(DWORD *)info = reply->debug_children;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
SERVER_END_REQ;
|
SERVER_END_REQ;
|
||||||
|
if (ret == STATUS_SUCCESS) NtClose( debug );
|
||||||
|
else if (ret == STATUS_PORT_NOT_SET) ret = STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else ret = STATUS_INFO_LENGTH_MISMATCH;
|
else ret = STATUS_INFO_LENGTH_MISMATCH;
|
||||||
|
@ -1408,17 +1421,19 @@ NTSTATUS WINAPI NtQueryInformationProcess( HANDLE handle, PROCESSINFOCLASS class
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ProcessDebugObjectHandle:
|
case ProcessDebugObjectHandle:
|
||||||
/* "These are not the debuggers you are looking for." *
|
|
||||||
* set it to 0 aka "no debugger" to satisfy copy protections */
|
|
||||||
len = sizeof(HANDLE);
|
len = sizeof(HANDLE);
|
||||||
if (size == len)
|
if (size == len)
|
||||||
{
|
{
|
||||||
if (!info) ret = STATUS_ACCESS_VIOLATION;
|
if (!info) ret = STATUS_ACCESS_VIOLATION;
|
||||||
else if (!handle) ret = STATUS_INVALID_HANDLE;
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memset(info, 0, size);
|
SERVER_START_REQ(get_process_debug_info)
|
||||||
ret = STATUS_PORT_NOT_SET;
|
{
|
||||||
|
req->handle = wine_server_obj_handle( handle );
|
||||||
|
ret = wine_server_call( req );
|
||||||
|
*(HANDLE *)info = wine_server_ptr_handle( reply->debug );
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else ret = STATUS_INFO_LENGTH_MISMATCH;
|
else ret = STATUS_INFO_LENGTH_MISMATCH;
|
||||||
|
|
|
@ -1008,8 +1008,22 @@ struct get_process_info_reply
|
||||||
int exit_code;
|
int exit_code;
|
||||||
int priority;
|
int priority;
|
||||||
client_cpu_t cpu;
|
client_cpu_t cpu;
|
||||||
short int debugger_present;
|
/* VARARG(image,pe_image_info); */
|
||||||
short int debug_children;
|
char __pad_60[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct get_process_debug_info_request
|
||||||
|
{
|
||||||
|
struct request_header __header;
|
||||||
|
obj_handle_t handle;
|
||||||
|
};
|
||||||
|
struct get_process_debug_info_reply
|
||||||
|
{
|
||||||
|
struct reply_header __header;
|
||||||
|
obj_handle_t debug;
|
||||||
|
int debug_children;
|
||||||
/* VARARG(image,pe_image_info); */
|
/* VARARG(image,pe_image_info); */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5427,6 +5441,7 @@ enum request
|
||||||
REQ_terminate_process,
|
REQ_terminate_process,
|
||||||
REQ_terminate_thread,
|
REQ_terminate_thread,
|
||||||
REQ_get_process_info,
|
REQ_get_process_info,
|
||||||
|
REQ_get_process_debug_info,
|
||||||
REQ_get_process_vm_counters,
|
REQ_get_process_vm_counters,
|
||||||
REQ_set_process_info,
|
REQ_set_process_info,
|
||||||
REQ_get_thread_info,
|
REQ_get_thread_info,
|
||||||
|
@ -5711,6 +5726,7 @@ union generic_request
|
||||||
struct terminate_process_request terminate_process_request;
|
struct terminate_process_request terminate_process_request;
|
||||||
struct terminate_thread_request terminate_thread_request;
|
struct terminate_thread_request terminate_thread_request;
|
||||||
struct get_process_info_request get_process_info_request;
|
struct get_process_info_request get_process_info_request;
|
||||||
|
struct get_process_debug_info_request get_process_debug_info_request;
|
||||||
struct get_process_vm_counters_request get_process_vm_counters_request;
|
struct get_process_vm_counters_request get_process_vm_counters_request;
|
||||||
struct set_process_info_request set_process_info_request;
|
struct set_process_info_request set_process_info_request;
|
||||||
struct get_thread_info_request get_thread_info_request;
|
struct get_thread_info_request get_thread_info_request;
|
||||||
|
@ -5993,6 +6009,7 @@ union generic_reply
|
||||||
struct terminate_process_reply terminate_process_reply;
|
struct terminate_process_reply terminate_process_reply;
|
||||||
struct terminate_thread_reply terminate_thread_reply;
|
struct terminate_thread_reply terminate_thread_reply;
|
||||||
struct get_process_info_reply get_process_info_reply;
|
struct get_process_info_reply get_process_info_reply;
|
||||||
|
struct get_process_debug_info_reply get_process_debug_info_reply;
|
||||||
struct get_process_vm_counters_reply get_process_vm_counters_reply;
|
struct get_process_vm_counters_reply get_process_vm_counters_reply;
|
||||||
struct set_process_info_reply set_process_info_reply;
|
struct set_process_info_reply set_process_info_reply;
|
||||||
struct get_thread_info_reply get_thread_info_reply;
|
struct get_thread_info_reply get_thread_info_reply;
|
||||||
|
@ -6263,7 +6280,7 @@ union generic_reply
|
||||||
|
|
||||||
/* ### protocol_version begin ### */
|
/* ### protocol_version begin ### */
|
||||||
|
|
||||||
#define SERVER_PROTOCOL_VERSION 668
|
#define SERVER_PROTOCOL_VERSION 669
|
||||||
|
|
||||||
/* ### protocol_version end ### */
|
/* ### protocol_version end ### */
|
||||||
|
|
||||||
|
|
|
@ -1422,8 +1422,6 @@ DECL_HANDLER(get_process_info)
|
||||||
reply->start_time = process->start_time;
|
reply->start_time = process->start_time;
|
||||||
reply->end_time = process->end_time;
|
reply->end_time = process->end_time;
|
||||||
reply->cpu = process->cpu;
|
reply->cpu = process->cpu;
|
||||||
reply->debugger_present = !!process->debug_obj;
|
|
||||||
reply->debug_children = process->debug_children;
|
|
||||||
if (get_reply_max_size())
|
if (get_reply_max_size())
|
||||||
{
|
{
|
||||||
client_ptr_t base;
|
client_ptr_t base;
|
||||||
|
@ -1436,6 +1434,19 @@ DECL_HANDLER(get_process_info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* retrieve debug information about a process */
|
||||||
|
DECL_HANDLER(get_process_debug_info)
|
||||||
|
{
|
||||||
|
struct process *process;
|
||||||
|
|
||||||
|
if (!(process = get_process_from_handle( req->handle, PROCESS_QUERY_LIMITED_INFORMATION ))) return;
|
||||||
|
|
||||||
|
reply->debug_children = process->debug_children;
|
||||||
|
if (!process->debug_obj) set_error( STATUS_PORT_NOT_SET );
|
||||||
|
else reply->debug = alloc_handle( current->process, process->debug_obj, DEBUG_ALL_ACCESS, 0 );
|
||||||
|
release_object( process );
|
||||||
|
}
|
||||||
|
|
||||||
/* retrieve information about a process memory usage */
|
/* retrieve information about a process memory usage */
|
||||||
DECL_HANDLER(get_process_vm_counters)
|
DECL_HANDLER(get_process_vm_counters)
|
||||||
{
|
{
|
||||||
|
|
|
@ -955,8 +955,16 @@ typedef struct
|
||||||
int exit_code; /* process exit code */
|
int exit_code; /* process exit code */
|
||||||
int priority; /* priority class */
|
int priority; /* priority class */
|
||||||
client_cpu_t cpu; /* CPU that this process is running on */
|
client_cpu_t cpu; /* CPU that this process is running on */
|
||||||
short int debugger_present; /* process is being debugged */
|
VARARG(image,pe_image_info); /* image info for main exe */
|
||||||
short int debug_children; /* inherit debugger to child processes */
|
@END
|
||||||
|
|
||||||
|
|
||||||
|
/* Retrieve debug information about a process */
|
||||||
|
@REQ(get_process_debug_info)
|
||||||
|
obj_handle_t handle; /* process handle */
|
||||||
|
@REPLY
|
||||||
|
obj_handle_t debug; /* handle to debug port */
|
||||||
|
int debug_children; /* inherit debugger to child processes */
|
||||||
VARARG(image,pe_image_info); /* image info for main exe */
|
VARARG(image,pe_image_info); /* image info for main exe */
|
||||||
@END
|
@END
|
||||||
|
|
||||||
|
|
|
@ -130,6 +130,7 @@ DECL_HANDLER(init_thread);
|
||||||
DECL_HANDLER(terminate_process);
|
DECL_HANDLER(terminate_process);
|
||||||
DECL_HANDLER(terminate_thread);
|
DECL_HANDLER(terminate_thread);
|
||||||
DECL_HANDLER(get_process_info);
|
DECL_HANDLER(get_process_info);
|
||||||
|
DECL_HANDLER(get_process_debug_info);
|
||||||
DECL_HANDLER(get_process_vm_counters);
|
DECL_HANDLER(get_process_vm_counters);
|
||||||
DECL_HANDLER(set_process_info);
|
DECL_HANDLER(set_process_info);
|
||||||
DECL_HANDLER(get_thread_info);
|
DECL_HANDLER(get_thread_info);
|
||||||
|
@ -413,6 +414,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
||||||
(req_handler)req_terminate_process,
|
(req_handler)req_terminate_process,
|
||||||
(req_handler)req_terminate_thread,
|
(req_handler)req_terminate_thread,
|
||||||
(req_handler)req_get_process_info,
|
(req_handler)req_get_process_info,
|
||||||
|
(req_handler)req_get_process_debug_info,
|
||||||
(req_handler)req_get_process_vm_counters,
|
(req_handler)req_get_process_vm_counters,
|
||||||
(req_handler)req_set_process_info,
|
(req_handler)req_set_process_info,
|
||||||
(req_handler)req_get_thread_info,
|
(req_handler)req_get_thread_info,
|
||||||
|
@ -799,9 +801,12 @@ C_ASSERT( FIELD_OFFSET(struct get_process_info_reply, end_time) == 40 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct get_process_info_reply, exit_code) == 48 );
|
C_ASSERT( FIELD_OFFSET(struct get_process_info_reply, exit_code) == 48 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct get_process_info_reply, priority) == 52 );
|
C_ASSERT( FIELD_OFFSET(struct get_process_info_reply, priority) == 52 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct get_process_info_reply, cpu) == 56 );
|
C_ASSERT( FIELD_OFFSET(struct get_process_info_reply, cpu) == 56 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct get_process_info_reply, debugger_present) == 60 );
|
|
||||||
C_ASSERT( FIELD_OFFSET(struct get_process_info_reply, debug_children) == 62 );
|
|
||||||
C_ASSERT( sizeof(struct get_process_info_reply) == 64 );
|
C_ASSERT( sizeof(struct get_process_info_reply) == 64 );
|
||||||
|
C_ASSERT( FIELD_OFFSET(struct get_process_debug_info_request, handle) == 12 );
|
||||||
|
C_ASSERT( sizeof(struct get_process_debug_info_request) == 16 );
|
||||||
|
C_ASSERT( FIELD_OFFSET(struct get_process_debug_info_reply, debug) == 8 );
|
||||||
|
C_ASSERT( FIELD_OFFSET(struct get_process_debug_info_reply, debug_children) == 12 );
|
||||||
|
C_ASSERT( sizeof(struct get_process_debug_info_reply) == 16 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct get_process_vm_counters_request, handle) == 12 );
|
C_ASSERT( FIELD_OFFSET(struct get_process_vm_counters_request, handle) == 12 );
|
||||||
C_ASSERT( sizeof(struct get_process_vm_counters_request) == 16 );
|
C_ASSERT( sizeof(struct get_process_vm_counters_request) == 16 );
|
||||||
C_ASSERT( FIELD_OFFSET(struct get_process_vm_counters_reply, peak_virtual_size) == 8 );
|
C_ASSERT( FIELD_OFFSET(struct get_process_vm_counters_reply, peak_virtual_size) == 8 );
|
||||||
|
|
|
@ -1506,7 +1506,17 @@ static void dump_get_process_info_reply( const struct get_process_info_reply *re
|
||||||
fprintf( stderr, ", exit_code=%d", req->exit_code );
|
fprintf( stderr, ", exit_code=%d", req->exit_code );
|
||||||
fprintf( stderr, ", priority=%d", req->priority );
|
fprintf( stderr, ", priority=%d", req->priority );
|
||||||
dump_client_cpu( ", cpu=", &req->cpu );
|
dump_client_cpu( ", cpu=", &req->cpu );
|
||||||
fprintf( stderr, ", debugger_present=%d", req->debugger_present );
|
dump_varargs_pe_image_info( ", image=", cur_size );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_get_process_debug_info_request( const struct get_process_debug_info_request *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " handle=%04x", req->handle );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_get_process_debug_info_reply( const struct get_process_debug_info_reply *req )
|
||||||
|
{
|
||||||
|
fprintf( stderr, " debug=%04x", req->debug );
|
||||||
fprintf( stderr, ", debug_children=%d", req->debug_children );
|
fprintf( stderr, ", debug_children=%d", req->debug_children );
|
||||||
dump_varargs_pe_image_info( ", image=", cur_size );
|
dump_varargs_pe_image_info( ", image=", cur_size );
|
||||||
}
|
}
|
||||||
|
@ -4471,6 +4481,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
||||||
(dump_func)dump_terminate_process_request,
|
(dump_func)dump_terminate_process_request,
|
||||||
(dump_func)dump_terminate_thread_request,
|
(dump_func)dump_terminate_thread_request,
|
||||||
(dump_func)dump_get_process_info_request,
|
(dump_func)dump_get_process_info_request,
|
||||||
|
(dump_func)dump_get_process_debug_info_request,
|
||||||
(dump_func)dump_get_process_vm_counters_request,
|
(dump_func)dump_get_process_vm_counters_request,
|
||||||
(dump_func)dump_set_process_info_request,
|
(dump_func)dump_set_process_info_request,
|
||||||
(dump_func)dump_get_thread_info_request,
|
(dump_func)dump_get_thread_info_request,
|
||||||
|
@ -4751,6 +4762,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
||||||
(dump_func)dump_terminate_process_reply,
|
(dump_func)dump_terminate_process_reply,
|
||||||
(dump_func)dump_terminate_thread_reply,
|
(dump_func)dump_terminate_thread_reply,
|
||||||
(dump_func)dump_get_process_info_reply,
|
(dump_func)dump_get_process_info_reply,
|
||||||
|
(dump_func)dump_get_process_debug_info_reply,
|
||||||
(dump_func)dump_get_process_vm_counters_reply,
|
(dump_func)dump_get_process_vm_counters_reply,
|
||||||
NULL,
|
NULL,
|
||||||
(dump_func)dump_get_thread_info_reply,
|
(dump_func)dump_get_thread_info_reply,
|
||||||
|
@ -5031,6 +5043,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
||||||
"terminate_process",
|
"terminate_process",
|
||||||
"terminate_thread",
|
"terminate_thread",
|
||||||
"get_process_info",
|
"get_process_info",
|
||||||
|
"get_process_debug_info",
|
||||||
"get_process_vm_counters",
|
"get_process_vm_counters",
|
||||||
"set_process_info",
|
"set_process_info",
|
||||||
"get_thread_info",
|
"get_thread_info",
|
||||||
|
@ -5408,6 +5421,7 @@ static const struct
|
||||||
{ "PIPE_EMPTY", STATUS_PIPE_EMPTY },
|
{ "PIPE_EMPTY", STATUS_PIPE_EMPTY },
|
||||||
{ "PIPE_LISTENING", STATUS_PIPE_LISTENING },
|
{ "PIPE_LISTENING", STATUS_PIPE_LISTENING },
|
||||||
{ "PIPE_NOT_AVAILABLE", STATUS_PIPE_NOT_AVAILABLE },
|
{ "PIPE_NOT_AVAILABLE", STATUS_PIPE_NOT_AVAILABLE },
|
||||||
|
{ "PORT_NOT_SET", STATUS_PORT_NOT_SET },
|
||||||
{ "PRIVILEGE_NOT_HELD", STATUS_PRIVILEGE_NOT_HELD },
|
{ "PRIVILEGE_NOT_HELD", STATUS_PRIVILEGE_NOT_HELD },
|
||||||
{ "PROCESS_IN_JOB", STATUS_PROCESS_IN_JOB },
|
{ "PROCESS_IN_JOB", STATUS_PROCESS_IN_JOB },
|
||||||
{ "PROCESS_IS_TERMINATING", STATUS_PROCESS_IS_TERMINATING },
|
{ "PROCESS_IS_TERMINATING", STATUS_PROCESS_IS_TERMINATING },
|
||||||
|
|
Loading…
Reference in New Issue