server: Store pointers to objects created by kernel_object_from_handle in server.
Signed-off-by: Jacek Caban <jacek@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
b2a546c92d
commit
134e264ae5
|
@ -264,13 +264,27 @@ static void free_kernel_object( void *obj )
|
|||
HeapFree( GetProcessHeap(), 0, header );
|
||||
}
|
||||
|
||||
void *alloc_kernel_object( POBJECT_TYPE type, SIZE_T size, LONG ref )
|
||||
void *alloc_kernel_object( POBJECT_TYPE type, HANDLE handle, SIZE_T size, LONG ref )
|
||||
{
|
||||
struct object_header *header;
|
||||
|
||||
if (!(header = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*header) + size)) )
|
||||
return NULL;
|
||||
|
||||
if (handle)
|
||||
{
|
||||
NTSTATUS status;
|
||||
SERVER_START_REQ( set_kernel_object_ptr )
|
||||
{
|
||||
req->manager = wine_server_obj_handle( get_device_manager() );
|
||||
req->handle = wine_server_obj_handle( handle );
|
||||
req->user_ptr = wine_server_client_ptr( header + 1 );
|
||||
status = wine_server_call( req );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (status) FIXME( "set_object_reference failed: %#x\n", status );
|
||||
}
|
||||
|
||||
header->ref = ref;
|
||||
header->type = type;
|
||||
return header + 1;
|
||||
|
@ -327,51 +341,91 @@ static const POBJECT_TYPE *known_types[] =
|
|||
&SeTokenObjectType
|
||||
};
|
||||
|
||||
static CRITICAL_SECTION handle_map_cs;
|
||||
static CRITICAL_SECTION_DEBUG handle_map_critsect_debug =
|
||||
{
|
||||
0, 0, &handle_map_cs,
|
||||
{ &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
|
||||
0, 0, { (DWORD_PTR)(__FILE__ ": handle_map_cs") }
|
||||
};
|
||||
static CRITICAL_SECTION handle_map_cs = { &handle_map_critsect_debug, -1, 0, 0, 0, 0 };
|
||||
|
||||
static NTSTATUS kernel_object_from_handle( HANDLE handle, POBJECT_TYPE type, void **ret )
|
||||
{
|
||||
char buf[256];
|
||||
OBJECT_TYPE_INFORMATION *type_info = (OBJECT_TYPE_INFORMATION *)buf;
|
||||
ULONG size;
|
||||
struct object_header *header;
|
||||
void *obj;
|
||||
NTSTATUS status;
|
||||
|
||||
status = NtQueryObject(handle, ObjectTypeInformation, buf, sizeof(buf), &size);
|
||||
if (status) return status;
|
||||
EnterCriticalSection( &handle_map_cs );
|
||||
|
||||
if (!type)
|
||||
SERVER_START_REQ( get_kernel_object_ptr )
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < ARRAY_SIZE(known_types); i++)
|
||||
{
|
||||
type = *known_types[i];
|
||||
if (!RtlCompareUnicodeStrings( type->name, strlenW(type->name), type_info->TypeName.Buffer,
|
||||
type_info->TypeName.Length / sizeof(WCHAR), FALSE ))
|
||||
break;
|
||||
}
|
||||
if (i == ARRAY_SIZE(known_types))
|
||||
{
|
||||
FIXME("Unsupported type %s\n", debugstr_us(&type_info->TypeName));
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
req->manager = wine_server_obj_handle( get_device_manager() );
|
||||
req->handle = wine_server_obj_handle( handle );
|
||||
status = wine_server_call( req );
|
||||
obj = wine_server_get_ptr( reply->user_ptr );
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
if (status)
|
||||
{
|
||||
LeaveCriticalSection( &handle_map_cs );
|
||||
return status;
|
||||
}
|
||||
else if (!!RtlCompareUnicodeStrings( type->name, strlenW(type->name), type_info->TypeName.Buffer,
|
||||
type_info->TypeName.Length / sizeof(WCHAR), FALSE ))
|
||||
return STATUS_OBJECT_TYPE_MISMATCH;
|
||||
|
||||
FIXME( "semi-stub: returning new %s object instance\n", debugstr_w(type->name) );
|
||||
|
||||
if (type->constructor)
|
||||
obj = type->constructor( handle );
|
||||
if (obj)
|
||||
{
|
||||
header = (struct object_header *)obj - 1;
|
||||
if (type && header->type != type) status = STATUS_OBJECT_TYPE_MISMATCH;
|
||||
}
|
||||
else
|
||||
{
|
||||
obj = alloc_kernel_object( type, 0, 0 );
|
||||
FIXME( "No constructor for type %s returning empty %p object\n", debugstr_w(type->name), obj );
|
||||
}
|
||||
if (!obj) return STATUS_NO_MEMORY;
|
||||
char buf[256];
|
||||
OBJECT_TYPE_INFORMATION *type_info = (OBJECT_TYPE_INFORMATION *)buf;
|
||||
ULONG size;
|
||||
|
||||
TRACE( "%p -> %p\n", handle, obj );
|
||||
*ret = obj;
|
||||
return STATUS_SUCCESS;
|
||||
status = NtQueryObject( handle, ObjectTypeInformation, buf, sizeof(buf), &size );
|
||||
if (status)
|
||||
{
|
||||
LeaveCriticalSection( &handle_map_cs );
|
||||
return status;
|
||||
}
|
||||
if (!type)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < ARRAY_SIZE(known_types); i++)
|
||||
{
|
||||
type = *known_types[i];
|
||||
if (!RtlCompareUnicodeStrings( type->name, strlenW(type->name), type_info->TypeName.Buffer,
|
||||
type_info->TypeName.Length / sizeof(WCHAR), FALSE ))
|
||||
break;
|
||||
}
|
||||
if (i == ARRAY_SIZE(known_types))
|
||||
{
|
||||
FIXME("Unsupported type %s\n", debugstr_us(&type_info->TypeName));
|
||||
LeaveCriticalSection( &handle_map_cs );
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
}
|
||||
else if (RtlCompareUnicodeStrings( type->name, strlenW(type->name), type_info->TypeName.Buffer,
|
||||
type_info->TypeName.Length / sizeof(WCHAR), FALSE) )
|
||||
{
|
||||
LeaveCriticalSection( &handle_map_cs );
|
||||
return STATUS_OBJECT_TYPE_MISMATCH;
|
||||
}
|
||||
|
||||
if (type->constructor)
|
||||
obj = type->constructor( handle );
|
||||
else
|
||||
{
|
||||
FIXME( "No constructor for type %s\n", debugstr_w(type->name) );
|
||||
obj = alloc_kernel_object( type, handle, 0, 0 );
|
||||
}
|
||||
if (!obj) status = STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
LeaveCriticalSection( &handle_map_cs );
|
||||
if (!status) *ret = obj;
|
||||
return status;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -422,7 +476,7 @@ POBJECT_TYPE IoFileObjectType = &file_type;
|
|||
static void *create_file_object( HANDLE handle )
|
||||
{
|
||||
FILE_OBJECT *file;
|
||||
if (!(file = alloc_kernel_object( IoFileObjectType, sizeof(*file), 0 ))) return NULL;
|
||||
if (!(file = alloc_kernel_object( IoFileObjectType, handle, sizeof(*file), 0 ))) return NULL;
|
||||
file->Type = 5; /* MSDN */
|
||||
file->Size = sizeof(*file);
|
||||
return file;
|
||||
|
@ -487,7 +541,7 @@ static NTSTATUS dispatch_create( const irp_params_t *params, void *in_buff, ULON
|
|||
FILE_OBJECT *file;
|
||||
DEVICE_OBJECT *device = wine_server_get_ptr( params->create.device );
|
||||
|
||||
if (!(file = alloc_kernel_object( IoFileObjectType, sizeof(*file), 1 ))) return STATUS_NO_MEMORY;
|
||||
if (!(file = alloc_kernel_object( IoFileObjectType, NULL, sizeof(*file), 1 ))) return STATUS_NO_MEMORY;
|
||||
|
||||
TRACE( "device %p -> file %p\n", device, file );
|
||||
|
||||
|
@ -1298,7 +1352,7 @@ NTSTATUS WINAPI IoCreateDriver( UNICODE_STRING *name, PDRIVER_INITIALIZE init )
|
|||
|
||||
TRACE("(%s, %p)\n", debugstr_us(name), init);
|
||||
|
||||
if (!(driver = alloc_kernel_object( IoDriverObjectType, sizeof(*driver), 1 )))
|
||||
if (!(driver = alloc_kernel_object( IoDriverObjectType, NULL, sizeof(*driver), 1 )))
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
if ((status = RtlDuplicateUnicodeString( 1, name, &driver->driver_obj.DriverName )))
|
||||
|
@ -1379,7 +1433,7 @@ NTSTATUS WINAPI IoCreateDevice( DRIVER_OBJECT *driver, ULONG ext_size,
|
|||
TRACE( "(%p, %u, %s, %u, %x, %u, %p)\n",
|
||||
driver, ext_size, debugstr_us(name), type, characteristics, exclusive, ret_device );
|
||||
|
||||
if (!(device = alloc_kernel_object( IoDeviceObjectType, sizeof(DEVICE_OBJECT) + ext_size, 1 )))
|
||||
if (!(device = alloc_kernel_object( IoDeviceObjectType, NULL, sizeof(DEVICE_OBJECT) + ext_size, 1 )))
|
||||
return STATUS_NO_MEMORY;
|
||||
|
||||
SERVER_START_REQ( create_device )
|
||||
|
|
|
@ -5247,6 +5247,36 @@ struct get_next_device_request_reply
|
|||
|
||||
|
||||
|
||||
struct get_kernel_object_ptr_request
|
||||
{
|
||||
struct request_header __header;
|
||||
obj_handle_t manager;
|
||||
obj_handle_t handle;
|
||||
char __pad_20[4];
|
||||
};
|
||||
struct get_kernel_object_ptr_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
client_ptr_t user_ptr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct set_kernel_object_ptr_request
|
||||
{
|
||||
struct request_header __header;
|
||||
obj_handle_t manager;
|
||||
obj_handle_t handle;
|
||||
char __pad_20[4];
|
||||
client_ptr_t user_ptr;
|
||||
};
|
||||
struct set_kernel_object_ptr_reply
|
||||
{
|
||||
struct reply_header __header;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct make_process_system_request
|
||||
{
|
||||
struct request_header __header;
|
||||
|
@ -5933,6 +5963,8 @@ enum request
|
|||
REQ_create_device,
|
||||
REQ_delete_device,
|
||||
REQ_get_next_device_request,
|
||||
REQ_get_kernel_object_ptr,
|
||||
REQ_set_kernel_object_ptr,
|
||||
REQ_make_process_system,
|
||||
REQ_get_token_statistics,
|
||||
REQ_create_completion,
|
||||
|
@ -6231,6 +6263,8 @@ union generic_request
|
|||
struct create_device_request create_device_request;
|
||||
struct delete_device_request delete_device_request;
|
||||
struct get_next_device_request_request get_next_device_request_request;
|
||||
struct get_kernel_object_ptr_request get_kernel_object_ptr_request;
|
||||
struct set_kernel_object_ptr_request set_kernel_object_ptr_request;
|
||||
struct make_process_system_request make_process_system_request;
|
||||
struct get_token_statistics_request get_token_statistics_request;
|
||||
struct create_completion_request create_completion_request;
|
||||
|
@ -6527,6 +6561,8 @@ union generic_reply
|
|||
struct create_device_reply create_device_reply;
|
||||
struct delete_device_reply delete_device_reply;
|
||||
struct get_next_device_request_reply get_next_device_request_reply;
|
||||
struct get_kernel_object_ptr_reply get_kernel_object_ptr_reply;
|
||||
struct set_kernel_object_ptr_reply set_kernel_object_ptr_reply;
|
||||
struct make_process_system_reply make_process_system_reply;
|
||||
struct get_token_statistics_reply get_token_statistics_reply;
|
||||
struct create_completion_reply create_completion_reply;
|
||||
|
@ -6556,6 +6592,6 @@ union generic_reply
|
|||
struct terminate_job_reply terminate_job_reply;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 573
|
||||
#define SERVER_PROTOCOL_VERSION 574
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -243,6 +243,49 @@ static int compare_kernel_object( const void *k, const struct wine_rb_entry *ent
|
|||
return memcmp( k, &ptr->user_ptr, sizeof(client_ptr_t) );
|
||||
}
|
||||
|
||||
static struct kernel_object *kernel_object_from_obj( struct device_manager *manager, struct object *obj )
|
||||
{
|
||||
struct kernel_object *kernel_object;
|
||||
struct list *list;
|
||||
|
||||
if (!(list = obj->ops->get_kernel_obj_list( obj ))) return NULL;
|
||||
LIST_FOR_EACH_ENTRY( kernel_object, list, struct kernel_object, list_entry )
|
||||
{
|
||||
if (kernel_object->manager != manager) continue;
|
||||
return kernel_object;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static client_ptr_t get_kernel_object_ptr( struct device_manager *manager, struct object *obj )
|
||||
{
|
||||
struct kernel_object *kernel_object = kernel_object_from_obj( manager, obj );
|
||||
return kernel_object ? kernel_object->user_ptr : 0;
|
||||
}
|
||||
|
||||
static struct kernel_object *set_kernel_object( struct device_manager *manager, struct object *obj, client_ptr_t user_ptr )
|
||||
{
|
||||
struct kernel_object *kernel_object;
|
||||
struct list *list;
|
||||
|
||||
if (!(list = obj->ops->get_kernel_obj_list( obj ))) return NULL;
|
||||
|
||||
if (!(kernel_object = malloc( sizeof(*kernel_object) ))) return NULL;
|
||||
kernel_object->manager = manager;
|
||||
kernel_object->user_ptr = user_ptr;
|
||||
kernel_object->object = obj;
|
||||
|
||||
if (wine_rb_put( &manager->kernel_objects, &user_ptr, &kernel_object->rb_entry ))
|
||||
{
|
||||
/* kernel_object pointer already set */
|
||||
free( kernel_object );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_add_head( list, &kernel_object->list_entry );
|
||||
return kernel_object;
|
||||
}
|
||||
|
||||
static void irp_call_dump( struct object *obj, int verbose )
|
||||
{
|
||||
struct irp_call *irp = (struct irp_call *)obj;
|
||||
|
@ -803,3 +846,47 @@ DECL_HANDLER(set_irp_result)
|
|||
release_object( irp );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* get kernel pointer from server object */
|
||||
DECL_HANDLER(get_kernel_object_ptr)
|
||||
{
|
||||
struct device_manager *manager;
|
||||
struct object *object = NULL;
|
||||
|
||||
if (!(manager = (struct device_manager *)get_handle_obj( current->process, req->manager,
|
||||
0, &device_manager_ops )))
|
||||
return;
|
||||
|
||||
if ((object = get_handle_obj( current->process, req->handle, 0, NULL )))
|
||||
{
|
||||
reply->user_ptr = get_kernel_object_ptr( manager, object );
|
||||
release_object( object );
|
||||
}
|
||||
|
||||
release_object( manager );
|
||||
}
|
||||
|
||||
|
||||
/* associate kernel pointer with server object */
|
||||
DECL_HANDLER(set_kernel_object_ptr)
|
||||
{
|
||||
struct device_manager *manager;
|
||||
struct object *object = NULL;
|
||||
|
||||
if (!(manager = (struct device_manager *)get_handle_obj( current->process, req->manager,
|
||||
0, &device_manager_ops )))
|
||||
return;
|
||||
|
||||
if (!(object = get_handle_obj( current->process, req->handle, 0, NULL )))
|
||||
{
|
||||
release_object( manager );
|
||||
return;
|
||||
}
|
||||
|
||||
if (!set_kernel_object( manager, object, req->user_ptr ))
|
||||
set_error( STATUS_INVALID_HANDLE );
|
||||
|
||||
release_object( object );
|
||||
release_object( manager );
|
||||
}
|
||||
|
|
|
@ -3623,6 +3623,23 @@ struct handle_info
|
|||
@END
|
||||
|
||||
|
||||
/* Get kernel pointer from server object */
|
||||
@REQ(get_kernel_object_ptr)
|
||||
obj_handle_t manager; /* handle to the device manager */
|
||||
obj_handle_t handle; /* object handle */
|
||||
@REPLY
|
||||
client_ptr_t user_ptr; /* kernel object pointer */
|
||||
@END
|
||||
|
||||
|
||||
/* Associate kernel pointer with server object */
|
||||
@REQ(set_kernel_object_ptr)
|
||||
obj_handle_t manager; /* handle to the device manager */
|
||||
obj_handle_t handle; /* object handle */
|
||||
client_ptr_t user_ptr; /* kernel object pointer */
|
||||
@END
|
||||
|
||||
|
||||
/* Make the current process a system process */
|
||||
@REQ(make_process_system)
|
||||
@REPLY
|
||||
|
|
|
@ -376,6 +376,8 @@ DECL_HANDLER(create_device_manager);
|
|||
DECL_HANDLER(create_device);
|
||||
DECL_HANDLER(delete_device);
|
||||
DECL_HANDLER(get_next_device_request);
|
||||
DECL_HANDLER(get_kernel_object_ptr);
|
||||
DECL_HANDLER(set_kernel_object_ptr);
|
||||
DECL_HANDLER(make_process_system);
|
||||
DECL_HANDLER(get_token_statistics);
|
||||
DECL_HANDLER(create_completion);
|
||||
|
@ -673,6 +675,8 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
|
|||
(req_handler)req_create_device,
|
||||
(req_handler)req_delete_device,
|
||||
(req_handler)req_get_next_device_request,
|
||||
(req_handler)req_get_kernel_object_ptr,
|
||||
(req_handler)req_set_kernel_object_ptr,
|
||||
(req_handler)req_make_process_system,
|
||||
(req_handler)req_get_token_statistics,
|
||||
(req_handler)req_create_completion,
|
||||
|
@ -2285,6 +2289,15 @@ C_ASSERT( FIELD_OFFSET(struct get_next_device_request_reply, client_tid) == 40 )
|
|||
C_ASSERT( FIELD_OFFSET(struct get_next_device_request_reply, in_size) == 44 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_next_device_request_reply, out_size) == 48 );
|
||||
C_ASSERT( sizeof(struct get_next_device_request_reply) == 56 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_kernel_object_ptr_request, manager) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_kernel_object_ptr_request, handle) == 16 );
|
||||
C_ASSERT( sizeof(struct get_kernel_object_ptr_request) == 24 );
|
||||
C_ASSERT( FIELD_OFFSET(struct get_kernel_object_ptr_reply, user_ptr) == 8 );
|
||||
C_ASSERT( sizeof(struct get_kernel_object_ptr_reply) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_kernel_object_ptr_request, manager) == 12 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_kernel_object_ptr_request, handle) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct set_kernel_object_ptr_request, user_ptr) == 24 );
|
||||
C_ASSERT( sizeof(struct set_kernel_object_ptr_request) == 32 );
|
||||
C_ASSERT( sizeof(struct make_process_system_request) == 16 );
|
||||
C_ASSERT( FIELD_OFFSET(struct make_process_system_reply, event) == 8 );
|
||||
C_ASSERT( sizeof(struct make_process_system_reply) == 16 );
|
||||
|
|
|
@ -4298,6 +4298,24 @@ static void dump_get_next_device_request_reply( const struct get_next_device_req
|
|||
dump_varargs_bytes( ", next_data=", cur_size );
|
||||
}
|
||||
|
||||
static void dump_get_kernel_object_ptr_request( const struct get_kernel_object_ptr_request *req )
|
||||
{
|
||||
fprintf( stderr, " manager=%04x", req->manager );
|
||||
fprintf( stderr, ", handle=%04x", req->handle );
|
||||
}
|
||||
|
||||
static void dump_get_kernel_object_ptr_reply( const struct get_kernel_object_ptr_reply *req )
|
||||
{
|
||||
dump_uint64( " user_ptr=", &req->user_ptr );
|
||||
}
|
||||
|
||||
static void dump_set_kernel_object_ptr_request( const struct set_kernel_object_ptr_request *req )
|
||||
{
|
||||
fprintf( stderr, " manager=%04x", req->manager );
|
||||
fprintf( stderr, ", handle=%04x", req->handle );
|
||||
dump_uint64( ", user_ptr=", &req->user_ptr );
|
||||
}
|
||||
|
||||
static void dump_make_process_system_request( const struct make_process_system_request *req )
|
||||
{
|
||||
}
|
||||
|
@ -4811,6 +4829,8 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_create_device_request,
|
||||
(dump_func)dump_delete_device_request,
|
||||
(dump_func)dump_get_next_device_request_request,
|
||||
(dump_func)dump_get_kernel_object_ptr_request,
|
||||
(dump_func)dump_set_kernel_object_ptr_request,
|
||||
(dump_func)dump_make_process_system_request,
|
||||
(dump_func)dump_get_token_statistics_request,
|
||||
(dump_func)dump_create_completion_request,
|
||||
|
@ -5105,6 +5125,8 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
|
|||
(dump_func)dump_create_device_reply,
|
||||
NULL,
|
||||
(dump_func)dump_get_next_device_request_reply,
|
||||
(dump_func)dump_get_kernel_object_ptr_reply,
|
||||
NULL,
|
||||
(dump_func)dump_make_process_system_reply,
|
||||
(dump_func)dump_get_token_statistics_reply,
|
||||
(dump_func)dump_create_completion_reply,
|
||||
|
@ -5399,6 +5421,8 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
|
|||
"create_device",
|
||||
"delete_device",
|
||||
"get_next_device_request",
|
||||
"get_kernel_object_ptr",
|
||||
"set_kernel_object_ptr",
|
||||
"make_process_system",
|
||||
"get_token_statistics",
|
||||
"create_completion",
|
||||
|
|
Loading…
Reference in New Issue