server: Use generic kernel object list to store client device pointer.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2019-03-27 17:43:27 +01:00 committed by Alexandre Julliard
parent abca25b30f
commit b4f78d6896
6 changed files with 68 additions and 70 deletions

View File

@ -1474,8 +1474,6 @@ static const WCHAR device_type_name[] = {'D','e','v','i','c','e',0};
static struct _OBJECT_TYPE device_type =
{
device_type_name,
NULL,
free_kernel_object
};
POBJECT_TYPE IoDeviceObjectType = &device_type;
@ -1491,7 +1489,6 @@ NTSTATUS WINAPI IoCreateDevice( DRIVER_OBJECT *driver, ULONG ext_size,
{
NTSTATUS status;
DEVICE_OBJECT *device;
HANDLE handle = 0;
HANDLE manager = get_device_manager();
TRACE( "(%p, %u, %s, %u, %x, %u, %p)\n",
@ -1500,34 +1497,32 @@ NTSTATUS WINAPI IoCreateDevice( DRIVER_OBJECT *driver, ULONG ext_size,
if (!(device = alloc_kernel_object( IoDeviceObjectType, NULL, sizeof(DEVICE_OBJECT) + ext_size, 1 )))
return STATUS_NO_MEMORY;
device->DriverObject = driver;
device->DeviceExtension = device + 1;
device->DeviceType = type;
device->StackSize = 1;
device->NextDevice = driver->DeviceObject;
driver->DeviceObject = device;
SERVER_START_REQ( create_device )
{
req->access = 0;
req->attributes = 0;
req->rootdir = 0;
req->manager = wine_server_obj_handle( manager );
req->user_ptr = wine_server_client_ptr( device );
if (name) wine_server_add_data( req, name->Buffer, name->Length );
if (!(status = wine_server_call( req ))) handle = wine_server_ptr_handle( reply->handle );
status = wine_server_call( req );
}
SERVER_END_REQ;
if (status == STATUS_SUCCESS)
if (status)
{
device->DriverObject = driver;
device->DeviceExtension = device + 1;
device->DeviceType = type;
device->StackSize = 1;
device->Reserved = handle;
device->NextDevice = driver->DeviceObject;
driver->DeviceObject = device;
*ret_device = device;
free_kernel_object( device );
return status;
}
else free_kernel_object( device );
return status;
*ret_device = device;
return STATUS_SUCCESS;
}
@ -1542,7 +1537,8 @@ void WINAPI IoDeleteDevice( DEVICE_OBJECT *device )
SERVER_START_REQ( delete_device )
{
req->handle = wine_server_obj_handle( device->Reserved );
req->manager = wine_server_obj_handle( get_device_manager() );
req->device = wine_server_client_ptr( device );
status = wine_server_call( req );
}
SERVER_END_REQ;
@ -1552,7 +1548,6 @@ void WINAPI IoDeleteDevice( DEVICE_OBJECT *device )
DEVICE_OBJECT **prev = &device->DriverObject->DeviceObject;
while (*prev && *prev != device) prev = &(*prev)->NextDevice;
if (*prev) *prev = (*prev)->NextDevice;
NtClose( device->Reserved );
ObDereferenceObject( device );
}
}

View File

@ -5202,19 +5202,15 @@ struct create_device_manager_reply
struct create_device_request
{
struct request_header __header;
unsigned int access;
unsigned int attributes;
obj_handle_t rootdir;
client_ptr_t user_ptr;
obj_handle_t manager;
/* VARARG(name,unicode_str); */
char __pad_36[4];
char __pad_28[4];
};
struct create_device_reply
{
struct reply_header __header;
obj_handle_t handle;
char __pad_12[4];
};
@ -5222,7 +5218,8 @@ struct create_device_reply
struct delete_device_request
{
struct request_header __header;
obj_handle_t handle;
obj_handle_t manager;
client_ptr_t device;
};
struct delete_device_reply
{
@ -6650,6 +6647,6 @@ union generic_reply
struct terminate_job_reply terminate_job_reply;
};
#define SERVER_PROTOCOL_VERSION 576
#define SERVER_PROTOCOL_VERSION 577
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */

View File

@ -127,7 +127,7 @@ struct device
struct object obj; /* object header */
struct device_manager *manager; /* manager for this device (or NULL if deleted) */
char *unix_path; /* path to unix device if any */
client_ptr_t user_ptr; /* opaque ptr for client side */
struct list kernel_object; /* list of kernel object pointers */
struct list entry; /* entry in device manager list */
struct list files; /* list of open files */
};
@ -137,6 +137,7 @@ static struct object_type *device_get_type( struct object *obj );
static void device_destroy( struct object *obj );
static struct object *device_open_file( struct object *obj, unsigned int access,
unsigned int sharing, unsigned int options );
static struct list *device_get_kernel_obj_list( struct object *obj );
static const struct object_ops device_ops =
{
@ -156,7 +157,7 @@ static const struct object_ops device_ops =
directory_link_name, /* link_name */
default_unlink_name, /* unlink_name */
device_open_file, /* open_file */
no_kernel_obj_list, /* get_kernel_obj_list */
device_get_kernel_obj_list, /* get_kernel_obj_list */
no_close_handle, /* close_handle */
device_destroy /* destroy */
};
@ -460,7 +461,7 @@ static struct object *device_open_file( struct object *obj, unsigned int access,
params.create.access = access;
params.create.sharing = sharing;
params.create.options = options;
params.create.device = file->device->user_ptr;
params.create.device = get_kernel_object_ptr( device->manager, &device->obj );
if ((irp = create_irp( file, &params, NULL )))
{
@ -471,6 +472,12 @@ static struct object *device_open_file( struct object *obj, unsigned int access,
return &file->obj;
}
static struct list *device_get_kernel_obj_list( struct object *obj )
{
struct device *device = (struct device *)obj;
return &device->kernel_object;
}
static void device_file_dump( struct object *obj, int verbose )
{
struct device_file *file = (struct device_file *)obj;
@ -614,20 +621,17 @@ static int device_file_ioctl( struct fd *fd, ioctl_code_t code, struct async *as
}
static struct device *create_device( struct object *root, const struct unicode_str *name,
struct device_manager *manager, unsigned int attr )
struct device_manager *manager )
{
struct device *device;
if ((device = create_named_object( root, &device_ops, name, attr, NULL )))
if ((device = create_named_object( root, &device_ops, name, 0, NULL )))
{
if (get_error() != STATUS_OBJECT_NAME_EXISTS)
{
/* initialize it if it didn't already exist */
device->unix_path = NULL;
device->manager = manager;
list_add_tail( &manager->devices, &device->entry );
list_init( &device->files );
}
device->unix_path = NULL;
device->manager = manager;
list_add_tail( &manager->devices, &device->entry );
list_init( &device->kernel_object );
list_init( &device->files );
}
return device;
}
@ -641,6 +645,7 @@ struct object *create_unix_device( struct object *root, const struct unicode_str
{
device->unix_path = strdup( unix_path );
device->manager = NULL; /* no manager, requests go straight to the Unix device */
list_init( &device->kernel_object );
list_init( &device->files );
}
return &device->obj;
@ -793,10 +798,13 @@ DECL_HANDLER(create_device)
return;
}
if ((device = create_device( root, &name, manager, req->attributes )))
if ((device = create_device( root, &name, manager )))
{
device->user_ptr = req->user_ptr;
reply->handle = alloc_handle( current->process, device, req->access, req->attributes );
struct kernel_object *ptr = set_kernel_object( manager, &device->obj, req->user_ptr );
if (ptr)
grab_kernel_object( ptr );
else
set_error( STATUS_NO_MEMORY );
release_object( device );
}
@ -808,13 +816,23 @@ DECL_HANDLER(create_device)
/* delete a device */
DECL_HANDLER(delete_device)
{
struct device_manager *manager;
struct kernel_object *ref;
struct device *device;
if ((device = (struct device *)get_handle_obj( current->process, req->handle, 0, &device_ops )))
if (!(manager = (struct device_manager *)get_handle_obj( current->process, req->manager,
0, &device_manager_ops )))
return;
if ((ref = kernel_object_from_ptr( manager, req->device )) && ref->object->ops == &device_ops)
{
device = (struct device *)grab_object( ref->object );
delete_device( device );
release_object( device );
}
else set_error( STATUS_INVALID_HANDLE );
release_object( manager );
}

View File

@ -3596,20 +3596,17 @@ struct handle_info
/* Create a device */
@REQ(create_device)
unsigned int access; /* wanted access rights */
unsigned int attributes; /* object attributes */
obj_handle_t rootdir; /* root directory */
client_ptr_t user_ptr; /* opaque ptr for use by client */
obj_handle_t manager; /* device manager */
VARARG(name,unicode_str); /* object name */
@REPLY
obj_handle_t handle; /* handle to the device */
@END
/* Delete a device */
@REQ(delete_device)
obj_handle_t handle; /* handle to the device */
obj_handle_t manager; /* handle to the device manager */
client_ptr_t device; /* pointer to the device */
@END

View File

@ -2274,16 +2274,13 @@ C_ASSERT( FIELD_OFFSET(struct create_device_manager_request, attributes) == 16 )
C_ASSERT( sizeof(struct create_device_manager_request) == 24 );
C_ASSERT( FIELD_OFFSET(struct create_device_manager_reply, handle) == 8 );
C_ASSERT( sizeof(struct create_device_manager_reply) == 16 );
C_ASSERT( FIELD_OFFSET(struct create_device_request, access) == 12 );
C_ASSERT( FIELD_OFFSET(struct create_device_request, attributes) == 16 );
C_ASSERT( FIELD_OFFSET(struct create_device_request, rootdir) == 20 );
C_ASSERT( FIELD_OFFSET(struct create_device_request, user_ptr) == 24 );
C_ASSERT( FIELD_OFFSET(struct create_device_request, manager) == 32 );
C_ASSERT( sizeof(struct create_device_request) == 40 );
C_ASSERT( FIELD_OFFSET(struct create_device_reply, handle) == 8 );
C_ASSERT( sizeof(struct create_device_reply) == 16 );
C_ASSERT( FIELD_OFFSET(struct delete_device_request, handle) == 12 );
C_ASSERT( sizeof(struct delete_device_request) == 16 );
C_ASSERT( FIELD_OFFSET(struct create_device_request, rootdir) == 12 );
C_ASSERT( FIELD_OFFSET(struct create_device_request, user_ptr) == 16 );
C_ASSERT( FIELD_OFFSET(struct create_device_request, manager) == 24 );
C_ASSERT( sizeof(struct create_device_request) == 32 );
C_ASSERT( FIELD_OFFSET(struct delete_device_request, manager) == 12 );
C_ASSERT( FIELD_OFFSET(struct delete_device_request, device) == 16 );
C_ASSERT( sizeof(struct delete_device_request) == 24 );
C_ASSERT( FIELD_OFFSET(struct get_next_device_request_request, manager) == 12 );
C_ASSERT( FIELD_OFFSET(struct get_next_device_request_request, prev) == 16 );
C_ASSERT( FIELD_OFFSET(struct get_next_device_request_request, status) == 20 );

View File

@ -4262,22 +4262,16 @@ static void dump_create_device_manager_reply( const struct create_device_manager
static void dump_create_device_request( const struct create_device_request *req )
{
fprintf( stderr, " access=%08x", req->access );
fprintf( stderr, ", attributes=%08x", req->attributes );
fprintf( stderr, ", rootdir=%04x", req->rootdir );
fprintf( stderr, " rootdir=%04x", req->rootdir );
dump_uint64( ", user_ptr=", &req->user_ptr );
fprintf( stderr, ", manager=%04x", req->manager );
dump_varargs_unicode_str( ", name=", cur_size );
}
static void dump_create_device_reply( const struct create_device_reply *req )
{
fprintf( stderr, " handle=%04x", req->handle );
}
static void dump_delete_device_request( const struct delete_device_request *req )
{
fprintf( stderr, " handle=%04x", req->handle );
fprintf( stderr, " manager=%04x", req->manager );
dump_uint64( ", device=", &req->device );
}
static void dump_get_next_device_request_request( const struct get_next_device_request_request *req )
@ -5149,7 +5143,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_get_token_impersonation_level_reply,
(dump_func)dump_allocate_locally_unique_id_reply,
(dump_func)dump_create_device_manager_reply,
(dump_func)dump_create_device_reply,
NULL,
NULL,
(dump_func)dump_get_next_device_request_reply,
(dump_func)dump_get_kernel_object_ptr_reply,