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
27 #define WIN32_NO_STATUS
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 */
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 */
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 */
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
);
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
;
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
);
205 /* create a device manager */
206 DECL_HANDLER(create_device_manager
)
208 struct device_manager
*manager
= create_device_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
)))
230 get_req_unicode_str( &name
);
231 if (req
->rootdir
&& !(root
= get_directory_obj( current
->process
, req
->rootdir
, 0 )))
233 release_object( manager
);
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
);