ntdll: Implement NtCreateDebugObject().
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
c1a042cefb
commit
5ebc20c656
|
@ -159,7 +159,7 @@
|
|||
# @ stub NtCompressKey
|
||||
@ stdcall -syscall NtConnectPort(ptr ptr ptr ptr ptr ptr ptr ptr)
|
||||
@ stdcall -syscall NtContinue(ptr long)
|
||||
# @ stub NtCreateDebugObject
|
||||
@ stdcall -syscall NtCreateDebugObject(ptr long ptr long)
|
||||
@ stdcall -syscall NtCreateDirectoryObject(ptr long ptr)
|
||||
@ stdcall -syscall NtCreateEvent(ptr long ptr long long)
|
||||
@ stub NtCreateEventPair
|
||||
|
|
|
@ -75,6 +75,7 @@ static NTSTATUS (WINAPI *pRtlWaitOnAddress)( const void *, const void *, SIZE_T,
|
|||
static void (WINAPI *pRtlWakeAddressAll)( const void * );
|
||||
static void (WINAPI *pRtlWakeAddressSingle)( const void * );
|
||||
static NTSTATUS (WINAPI *pNtOpenProcess)( HANDLE *, ACCESS_MASK, const OBJECT_ATTRIBUTES *, const CLIENT_ID * );
|
||||
static NTSTATUS (WINAPI *pNtCreateDebugObject)( HANDLE *, ACCESS_MASK, OBJECT_ATTRIBUTES *, ULONG );
|
||||
|
||||
#define KEYEDEVENT_WAIT 0x0001
|
||||
#define KEYEDEVENT_WAKE 0x0002
|
||||
|
@ -418,6 +419,9 @@ static void test_all_kernel_objects( UINT line, OBJECT_ATTRIBUTES *attr,
|
|||
ok( status2 == open_expect, "%u: NtOpenSection failed %x\n", line, status2 );
|
||||
if (!status) pNtClose( ret );
|
||||
if (!status2) pNtClose( ret2 );
|
||||
status = pNtCreateDebugObject( &ret, DEBUG_ALL_ACCESS, attr, 0 );
|
||||
ok( status == create_expect, "%u: NtCreateDebugObject failed %x\n", line, status );
|
||||
if (!status) pNtClose( ret );
|
||||
}
|
||||
|
||||
static void test_name_limits(void)
|
||||
|
@ -1450,6 +1454,15 @@ static void test_query_object(void)
|
|||
|
||||
pNtClose( handle );
|
||||
|
||||
RtlInitUnicodeString( &path, L"\\BaseNamedObjects\\test_debug" );
|
||||
status = pNtCreateDebugObject( &handle, DEBUG_ALL_ACCESS, &attr, 0 );
|
||||
ok(!status, "NtCreateDebugObject failed: %x\n", status);
|
||||
|
||||
test_object_name( handle, L"\\BaseNamedObjects\\test_debug", FALSE );
|
||||
test_object_type( handle, L"DebugObject" );
|
||||
test_no_file_info( handle );
|
||||
pNtClose(handle);
|
||||
|
||||
status = pNtCreateDirectoryObject( &handle, DIRECTORY_QUERY, NULL );
|
||||
ok(status == STATUS_SUCCESS, "Failed to create Directory %08x\n", status);
|
||||
|
||||
|
@ -2294,6 +2307,7 @@ START_TEST(om)
|
|||
pRtlWakeAddressAll = (void *)GetProcAddress(hntdll, "RtlWakeAddressAll");
|
||||
pRtlWakeAddressSingle = (void *)GetProcAddress(hntdll, "RtlWakeAddressSingle");
|
||||
pNtOpenProcess = (void *)GetProcAddress(hntdll, "NtOpenProcess");
|
||||
pNtCreateDebugObject = (void *)GetProcAddress(hntdll, "NtCreateDebugObject");
|
||||
|
||||
test_case_sensitive();
|
||||
test_namespace_pipe();
|
||||
|
|
|
@ -906,6 +906,31 @@ NTSTATUS WINAPI NtAssignProcessToJobObject( HANDLE job, HANDLE process )
|
|||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NtCreateDebugObject (NTDLL.@)
|
||||
*/
|
||||
NTSTATUS WINAPI NtCreateDebugObject( HANDLE *handle, ACCESS_MASK access,
|
||||
OBJECT_ATTRIBUTES *attr, ULONG flags )
|
||||
{
|
||||
NTSTATUS ret;
|
||||
data_size_t len;
|
||||
struct object_attributes *objattr;
|
||||
|
||||
if ((ret = alloc_object_attributes( attr, &objattr, &len ))) return ret;
|
||||
|
||||
SERVER_START_REQ( create_debug_obj )
|
||||
{
|
||||
req->access = access;
|
||||
wine_server_add_data( req, objattr, len );
|
||||
ret = wine_server_call( req );
|
||||
*handle = wine_server_ptr_handle( reply->handle );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
free( objattr );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* NtCreateDirectoryObject (NTDLL.@)
|
||||
*/
|
||||
|
|
|
@ -2008,6 +2008,21 @@ struct list_processes_reply
|
|||
|
||||
|
||||
|
||||
struct create_debug_obj_request
|
||||
{
|
||||
struct request_header __header;
|
||||
unsigned int access;
|
||||
/* VARARG(objattr,object_attributes); */
|
||||
};
|
||||
struct create_debug_obj_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
obj_handle_t handle;
|
||||
char __pad_12[4];
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct wait_debug_event_request
|
||||
{
|
||||
struct request_header __header;
|
||||
|
@ -5422,6 +5437,7 @@ enum request
|
|||
REQ_add_mapping_committed_range,
|
||||
REQ_is_same_mapping,
|
||||
REQ_list_processes,
|
||||
REQ_create_debug_obj,
|
||||
REQ_wait_debug_event,
|
||||
REQ_queue_exception_event,
|
||||
REQ_get_exception_status,
|
||||
|
@ -5703,6 +5719,7 @@ union generic_request
|
|||
struct add_mapping_committed_range_request add_mapping_committed_range_request;
|
||||
struct is_same_mapping_request is_same_mapping_request;
|
||||
struct list_processes_request list_processes_request;
|
||||
struct create_debug_obj_request create_debug_obj_request;
|
||||
struct wait_debug_event_request wait_debug_event_request;
|
||||
struct queue_exception_event_request queue_exception_event_request;
|
||||
struct get_exception_status_request get_exception_status_request;
|
||||
|
@ -5982,6 +5999,7 @@ union generic_reply
|
|||
struct add_mapping_committed_range_reply add_mapping_committed_range_reply;
|
||||
struct is_same_mapping_reply is_same_mapping_reply;
|
||||
struct list_processes_reply list_processes_reply;
|
||||
struct create_debug_obj_reply create_debug_obj_reply;
|
||||
struct wait_debug_event_reply wait_debug_event_reply;
|
||||
struct queue_exception_event_reply queue_exception_event_reply;
|
||||
struct get_exception_status_reply get_exception_status_reply;
|
||||
|
@ -6189,7 +6207,7 @@ union generic_reply
|
|||
|
||||
/* ### protocol_version begin ### */
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 655
|
||||
#define SERVER_PROTOCOL_VERSION 656
|
||||
|
||||
/* ### protocol_version end ### */
|
||||
|
||||
|
|
|
@ -3007,6 +3007,12 @@ typedef struct _PS_CREATE_INFO
|
|||
};
|
||||
} PS_CREATE_INFO, *PPS_CREATE_INFO;
|
||||
|
||||
#define DEBUG_READ_EVENT 0x0001
|
||||
#define DEBUG_PROCESS_ASSIGN 0x0002
|
||||
#define DEBUG_SET_INFORMATION 0x0004
|
||||
#define DEBUG_QUERY_INFORMATION 0x0008
|
||||
#define DEBUG_ALL_ACCESS (STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x0f)
|
||||
|
||||
/***********************************************************************
|
||||
* Function declarations
|
||||
*/
|
||||
|
@ -3067,6 +3073,7 @@ NTSYSAPI NTSTATUS WINAPI NtCloseObjectAuditAlarm(PUNICODE_STRING,HANDLE,BOOLEAN
|
|||
NTSYSAPI NTSTATUS WINAPI NtCompleteConnectPort(HANDLE);
|
||||
NTSYSAPI NTSTATUS WINAPI NtConnectPort(PHANDLE,PUNICODE_STRING,PSECURITY_QUALITY_OF_SERVICE,PLPC_SECTION_WRITE,PLPC_SECTION_READ,PULONG,PVOID,PULONG);
|
||||
NTSYSAPI NTSTATUS WINAPI NtContinue(PCONTEXT,BOOLEAN);
|
||||
NTSYSAPI NTSTATUS WINAPI NtCreateDebugObject(HANDLE*,ACCESS_MASK,OBJECT_ATTRIBUTES*,ULONG);
|
||||
NTSYSAPI NTSTATUS WINAPI NtCreateDirectoryObject(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES);
|
||||
NTSYSAPI NTSTATUS WINAPI NtCreateEvent(PHANDLE,ACCESS_MASK,const OBJECT_ATTRIBUTES *,EVENT_TYPE,BOOLEAN);
|
||||
NTSYSAPI NTSTATUS WINAPI NtCreateEventPair(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES);
|
||||
|
|
|
@ -90,27 +90,29 @@ static const struct object_ops debug_event_ops =
|
|||
};
|
||||
|
||||
static void debug_obj_dump( struct object *obj, int verbose );
|
||||
static struct object_type *debug_obj_get_type( struct object *obj );
|
||||
static int debug_obj_signaled( struct object *obj, struct wait_queue_entry *entry );
|
||||
static unsigned int debug_obj_map_access( struct object *obj, unsigned int access );
|
||||
static void debug_obj_destroy( struct object *obj );
|
||||
|
||||
static const struct object_ops debug_obj_ops =
|
||||
{
|
||||
sizeof(struct debug_obj), /* size */
|
||||
debug_obj_dump, /* dump */
|
||||
no_get_type, /* get_type */
|
||||
debug_obj_get_type, /* get_type */
|
||||
add_queue, /* add_queue */
|
||||
remove_queue, /* remove_queue */
|
||||
debug_obj_signaled, /* signaled */
|
||||
no_satisfied, /* satisfied */
|
||||
no_signal, /* signal */
|
||||
no_get_fd, /* get_fd */
|
||||
no_map_access, /* map_access */
|
||||
debug_obj_map_access, /* map_access */
|
||||
default_get_sd, /* get_sd */
|
||||
default_set_sd, /* set_sd */
|
||||
no_get_full_name, /* get_full_name */
|
||||
default_get_full_name, /* get_full_name */
|
||||
no_lookup_name, /* lookup_name */
|
||||
no_link_name, /* link_name */
|
||||
NULL, /* unlink_name */
|
||||
directory_link_name, /* link_name */
|
||||
default_unlink_name, /* unlink_name */
|
||||
no_open_file, /* open_file */
|
||||
no_kernel_obj_list, /* get_kernel_obj_list */
|
||||
no_close_handle, /* close_handle */
|
||||
|
@ -360,6 +362,13 @@ static void debug_obj_dump( struct object *obj, int verbose )
|
|||
debug_obj->event_queue.next, debug_obj->event_queue.prev );
|
||||
}
|
||||
|
||||
static struct object_type *debug_obj_get_type( struct object *obj )
|
||||
{
|
||||
static const WCHAR name[] = {'D','e','b','u','g','O','b','j','e','c','t'};
|
||||
static const struct unicode_str str = { name, sizeof(name) };
|
||||
return get_object_type( &str );
|
||||
}
|
||||
|
||||
static int debug_obj_signaled( struct object *obj, struct wait_queue_entry *entry )
|
||||
{
|
||||
struct debug_obj *debug_obj = (struct debug_obj *)obj;
|
||||
|
@ -367,6 +376,15 @@ static int debug_obj_signaled( struct object *obj, struct wait_queue_entry *entr
|
|||
return find_event_to_send( debug_obj ) != NULL;
|
||||
}
|
||||
|
||||
static unsigned int debug_obj_map_access( struct object *obj, unsigned int access )
|
||||
{
|
||||
if (access & GENERIC_READ) access |= STANDARD_RIGHTS_READ | DEBUG_READ_EVENT | DEBUG_QUERY_INFORMATION;
|
||||
if (access & GENERIC_WRITE) access |= STANDARD_RIGHTS_WRITE | DEBUG_SET_INFORMATION;
|
||||
if (access & GENERIC_EXECUTE) access |= STANDARD_RIGHTS_EXECUTE | DEBUG_PROCESS_ASSIGN;
|
||||
if (access & GENERIC_ALL) access |= STANDARD_RIGHTS_ALL | EVENT_QUERY_STATE | EVENT_MODIFY_STATE;
|
||||
return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
|
||||
}
|
||||
|
||||
static void debug_obj_destroy( struct object *obj )
|
||||
{
|
||||
struct list *ptr;
|
||||
|
@ -378,6 +396,22 @@ static void debug_obj_destroy( struct object *obj )
|
|||
unlink_event( debug_obj, LIST_ENTRY( ptr, struct debug_event, entry ));
|
||||
}
|
||||
|
||||
static struct debug_obj *create_debug_obj( struct object *root, const struct unicode_str *name,
|
||||
unsigned int attr, const struct security_descriptor *sd )
|
||||
{
|
||||
struct debug_obj *debug_obj;
|
||||
|
||||
if ((debug_obj = create_named_object( root, &debug_obj_ops, name, attr, sd )))
|
||||
{
|
||||
if (get_error() != STATUS_OBJECT_NAME_EXISTS)
|
||||
{
|
||||
debug_obj->kill_on_exit = 1;
|
||||
list_init( &debug_obj->event_queue );
|
||||
}
|
||||
}
|
||||
return debug_obj;
|
||||
}
|
||||
|
||||
/* continue a debug event */
|
||||
static int continue_debug_event( struct process *process, struct thread *thread, int status )
|
||||
{
|
||||
|
@ -640,6 +674,28 @@ void debug_exit_thread( struct thread *thread )
|
|||
}
|
||||
}
|
||||
|
||||
/* create a debug object */
|
||||
DECL_HANDLER(create_debug_obj)
|
||||
{
|
||||
struct debug_obj *debug_obj;
|
||||
struct unicode_str name;
|
||||
struct object *root;
|
||||
const struct security_descriptor *sd;
|
||||
const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, &root );
|
||||
|
||||
if (!objattr) return;
|
||||
if ((debug_obj = create_debug_obj( root, &name, objattr->attributes, sd )))
|
||||
{
|
||||
if (get_error() == STATUS_OBJECT_NAME_EXISTS)
|
||||
reply->handle = alloc_handle( current->process, debug_obj, req->access, objattr->attributes );
|
||||
else
|
||||
reply->handle = alloc_handle_no_access_check( current->process, debug_obj,
|
||||
req->access, objattr->attributes );
|
||||
release_object( debug_obj );
|
||||
}
|
||||
if (root) release_object( root );
|
||||
}
|
||||
|
||||
/* Wait for a debug event */
|
||||
DECL_HANDLER(wait_debug_event)
|
||||
{
|
||||
|
|
|
@ -1587,6 +1587,15 @@ struct process_info
|
|||
@END
|
||||
|
||||
|
||||
/* Create a debug object */
|
||||
@REQ(create_debug_obj)
|
||||
unsigned int access; /* wanted access rights */
|
||||
VARARG(objattr,object_attributes); /* object attributes */
|
||||
@REPLY
|
||||
obj_handle_t handle; /* handle to the debug object */
|
||||
@END
|
||||
|
||||
|
||||
/* Wait for a debug event */
|
||||
@REQ(wait_debug_event)
|
||||
int get_handle; /* should we alloc a handle for waiting? */
|
||||
|
|
|
@ -190,6 +190,7 @@ DECL_HANDLER(get_mapping_committed_range);
|
|||
DECL_HANDLER(add_mapping_committed_range);
|
||||
DECL_HANDLER(is_same_mapping);
|
||||
DECL_HANDLER(list_processes);
|
||||
DECL_HANDLER(create_debug_obj);
|
||||
DECL_HANDLER(wait_debug_event);
|
||||
DECL_HANDLER(queue_exception_event);
|
||||
DECL_HANDLER(get_exception_status);
|
||||
|
@ -470,6 +471,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
|||
(req_handler)req_add_mapping_committed_range,
|
||||
(req_handler)req_is_same_mapping,
|
||||
(req_handler)req_list_processes,
|
||||
(req_handler)req_create_debug_obj,
|
||||
(req_handler)req_wait_debug_event,
|
||||
(req_handler)req_queue_exception_event,
|
||||
(req_handler)req_get_exception_status,
|
||||
|
@ -1130,6 +1132,10 @@ C_ASSERT( sizeof(struct list_processes_request) == 16 );
|
|||
C_ASSERT( FIELD_OFFSET(struct list_processes_reply, info_size) == 8 );
|
||||
C_ASSERT( FIELD_OFFSET(struct list_processes_reply, process_count) == 12 );
|
||||
C_ASSERT( sizeof(struct list_processes_reply) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct create_debug_obj_request, access) == 12 );
|
||||
C_ASSERT( sizeof(struct create_debug_obj_request) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct create_debug_obj_reply, handle) == 8 );
|
||||
C_ASSERT( sizeof(struct create_debug_obj_reply) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct wait_debug_event_request, get_handle) == 12 );
|
||||
C_ASSERT( sizeof(struct wait_debug_event_request) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct wait_debug_event_reply, pid) == 8 );
|
||||
|
|
|
@ -2150,6 +2150,17 @@ static void dump_list_processes_reply( const struct list_processes_reply *req )
|
|||
dump_varargs_process_info( ", data=", min(cur_size,req->info_size) );
|
||||
}
|
||||
|
||||
static void dump_create_debug_obj_request( const struct create_debug_obj_request *req )
|
||||
{
|
||||
fprintf( stderr, " access=%08x", req->access );
|
||||
dump_varargs_object_attributes( ", objattr=", cur_size );
|
||||
}
|
||||
|
||||
static void dump_create_debug_obj_reply( const struct create_debug_obj_reply *req )
|
||||
{
|
||||
fprintf( stderr, " handle=%04x", req->handle );
|
||||
}
|
||||
|
||||
static void dump_wait_debug_event_request( const struct wait_debug_event_request *req )
|
||||
{
|
||||
fprintf( stderr, " get_handle=%d", req->get_handle );
|
||||
|
@ -4455,6 +4466,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_add_mapping_committed_range_request,
|
||||
(dump_func)dump_is_same_mapping_request,
|
||||
(dump_func)dump_list_processes_request,
|
||||
(dump_func)dump_create_debug_obj_request,
|
||||
(dump_func)dump_wait_debug_event_request,
|
||||
(dump_func)dump_queue_exception_event_request,
|
||||
(dump_func)dump_get_exception_status_request,
|
||||
|
@ -4732,6 +4744,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
NULL,
|
||||
NULL,
|
||||
(dump_func)dump_list_processes_reply,
|
||||
(dump_func)dump_create_debug_obj_reply,
|
||||
(dump_func)dump_wait_debug_event_reply,
|
||||
(dump_func)dump_queue_exception_event_reply,
|
||||
NULL,
|
||||
|
@ -5009,6 +5022,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
|||
"add_mapping_committed_range",
|
||||
"is_same_mapping",
|
||||
"list_processes",
|
||||
"create_debug_obj",
|
||||
"wait_debug_event",
|
||||
"queue_exception_event",
|
||||
"get_exception_status",
|
||||
|
|
Loading…
Reference in New Issue