server: Add support for generic device objects managed from the client side.
[wine/dibdrv.git] / server / device.c
blob8a911b791eca77030f68cedf0a10e16f298ce3ee
1 /*
2 * Server-side device support
4 * Copyright (C) 2007 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include <assert.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stdarg.h>
26 #include "ntstatus.h"
27 #define WIN32_NO_STATUS
28 #include "windef.h"
29 #include "winternl.h"
31 #include "object.h"
32 #include "file.h"
33 #include "handle.h"
34 #include "request.h"
36 struct device_manager
38 struct object obj; /* object header */
39 struct list devices; /* list of devices */
42 static void device_manager_dump( struct object *obj, int verbose );
43 static void device_manager_destroy( struct object *obj );
45 static const struct object_ops device_manager_ops =
47 sizeof(struct device_manager), /* size */
48 device_manager_dump, /* dump */
49 no_add_queue, /* add_queue */
50 NULL, /* remove_queue */
51 NULL, /* signaled */
52 no_satisfied, /* satisfied */
53 no_signal, /* signal */
54 no_get_fd, /* get_fd */
55 no_map_access, /* map_access */
56 no_lookup_name, /* lookup_name */
57 no_open_file, /* open_file */
58 no_close_handle, /* close_handle */
59 device_manager_destroy /* destroy */
63 struct device
65 struct object obj; /* object header */
66 struct device_manager *manager; /* manager for this device (or NULL if deleted) */
67 struct fd *fd; /* file descriptor for ioctl */
68 void *user_ptr; /* opaque ptr for client side */
69 struct list entry; /* entry in device manager list */
72 static void device_dump( struct object *obj, int verbose );
73 static struct fd *device_get_fd( struct object *obj );
74 static void device_destroy( struct object *obj );
75 static struct object *device_open_file( struct object *obj, unsigned int access,
76 unsigned int sharing, unsigned int options );
77 static enum server_fd_type device_get_fd_type( struct fd *fd );
79 static const struct object_ops device_ops =
81 sizeof(struct device), /* size */
82 device_dump, /* dump */
83 no_add_queue, /* add_queue */
84 NULL, /* remove_queue */
85 NULL, /* signaled */
86 no_satisfied, /* satisfied */
87 no_signal, /* signal */
88 device_get_fd, /* get_fd */
89 no_map_access, /* map_access */
90 no_lookup_name, /* lookup_name */
91 device_open_file, /* open_file */
92 no_close_handle, /* close_handle */
93 device_destroy /* destroy */
96 static const struct fd_ops device_fd_ops =
98 default_fd_get_poll_events, /* get_poll_events */
99 default_poll_event, /* poll_event */
100 no_flush, /* flush */
101 device_get_fd_type, /* get_fd_type */
102 default_fd_ioctl, /* ioctl */
103 default_fd_queue_async, /* queue_async */
104 default_fd_reselect_async, /* reselect_async */
105 default_fd_cancel_async /* cancel_async */
109 static void device_dump( struct object *obj, int verbose )
111 struct device *device = (struct device *)obj;
113 fprintf( stderr, "Device " );
114 dump_object_name( &device->obj );
115 fputc( '\n', stderr );
118 static struct fd *device_get_fd( struct object *obj )
120 struct device *device = (struct device *)obj;
122 return (struct fd *)grab_object( device->fd );
125 static void device_destroy( struct object *obj )
127 struct device *device = (struct device *)obj;
129 if (device->fd) release_object( device->fd );
130 if (device->manager) list_remove( &device->entry );
133 static struct object *device_open_file( struct object *obj, unsigned int access,
134 unsigned int sharing, unsigned int options )
136 return grab_object( obj );
139 static enum server_fd_type device_get_fd_type( struct fd *fd )
141 return FD_TYPE_DEVICE;
144 static struct device *create_device( struct directory *root, const struct unicode_str *name,
145 struct device_manager *manager, unsigned int attr )
147 struct device *device;
149 if ((device = create_named_object_dir( root, name, attr, &device_ops )))
151 if (get_error() != STATUS_OBJECT_NAME_EXISTS)
153 /* initialize it if it didn't already exist */
154 device->manager = manager;
155 list_add_tail( &manager->devices, &device->entry );
156 if (!(device->fd = alloc_pseudo_fd( &device_fd_ops, &device->obj, 0 )))
158 release_object( device );
159 device = NULL;
163 return device;
166 static void delete_device( struct device *device )
168 if (!device->manager) return; /* already deleted */
170 unlink_named_object( &device->obj );
171 list_remove( &device->entry );
172 device->manager = NULL;
176 static void device_manager_dump( struct object *obj, int verbose )
178 fprintf( stderr, "Device manager\n" );
181 static void device_manager_destroy( struct object *obj )
183 struct device_manager *manager = (struct device_manager *)obj;
184 struct list *ptr;
186 while ((ptr = list_head( &manager->devices )))
188 struct device *device = LIST_ENTRY( ptr, struct device, entry );
189 delete_device( device );
193 static struct device_manager *create_device_manager(void)
195 struct device_manager *manager;
197 if ((manager = alloc_object( &device_manager_ops )))
199 list_init( &manager->devices );
201 return manager;
205 /* create a device manager */
206 DECL_HANDLER(create_device_manager)
208 struct device_manager *manager = create_device_manager();
210 if (manager)
212 reply->handle = alloc_handle( current->process, manager, req->access, req->attributes );
213 release_object( manager );
218 /* create a device */
219 DECL_HANDLER(create_device)
221 struct device *device;
222 struct unicode_str name;
223 struct device_manager *manager;
224 struct directory *root = NULL;
226 if (!(manager = (struct device_manager *)get_handle_obj( current->process, req->manager,
227 0, &device_manager_ops )))
228 return;
230 get_req_unicode_str( &name );
231 if (req->rootdir && !(root = get_directory_obj( current->process, req->rootdir, 0 )))
233 release_object( manager );
234 return;
237 if ((device = create_device( root, &name, manager, req->attributes )))
239 device->user_ptr = req->user_ptr;
240 reply->handle = alloc_handle( current->process, device, req->access, req->attributes );
241 release_object( device );
244 if (root) release_object( root );
245 release_object( manager );
249 /* delete a device */
250 DECL_HANDLER(delete_device)
252 struct device *device;
254 if ((device = (struct device *)get_handle_obj( current->process, req->handle, 0, &device_ops )))
256 delete_device( device );
257 release_object( device );