ntdll: Implement NtCreateDebugObject().

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-01-27 10:43:30 +01:00
parent c1a042cefb
commit 5ebc20c656
9 changed files with 156 additions and 7 deletions

View File

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

View File

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

View File

@ -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.@)
*/

View File

@ -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 ### */

View File

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

View File

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

View File

@ -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? */

View File

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

View File

@ -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",