get_window_children: only decrement available size if element was
[wine] / server / object.c
1 /*
2  * Server-side objects
3  * These are the server equivalent of K32OBJ
4  *
5  * Copyright (C) 1998 Alexandre Julliard
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include <assert.h>
23 #include <limits.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <unistd.h>
28
29 #include "thread.h"
30 #include "unicode.h"
31
32
33 struct object_name
34 {
35     struct object_name *next;
36     struct object_name *prev;
37     struct object      *obj;
38     size_t              len;
39     WCHAR               name[1];
40 };
41
42 #define NAME_HASH_SIZE 37
43
44 static struct object_name *names[NAME_HASH_SIZE];
45
46 #ifdef DEBUG_OBJECTS
47 static struct object *first;
48
49 void dump_objects(void)
50 {
51     struct object *ptr = first;
52     while (ptr)
53     {
54         fprintf( stderr, "%p:%d: ", ptr, ptr->refcount );
55         ptr->ops->dump( ptr, 1 );
56         ptr = ptr->next;
57     }
58 }
59 #endif
60
61 /*****************************************************************/
62
63 /* malloc replacement */
64 void *mem_alloc( size_t size )
65 {
66     void *ptr = malloc( size );
67     if (ptr) memset( ptr, 0x55, size );
68     else set_error( STATUS_NO_MEMORY );
69     return ptr;
70 }
71
72 /* duplicate a block of memory */
73 void *memdup( const void *data, size_t len )
74 {
75     void *ptr = malloc( len );
76     if (ptr) memcpy( ptr, data, len );
77     else set_error( STATUS_NO_MEMORY );
78     return ptr;
79 }
80
81
82 /*****************************************************************/
83
84 static int get_name_hash( const WCHAR *name, size_t len )
85 {
86     WCHAR hash = 0;
87     len /= sizeof(WCHAR);
88     while (len--) hash ^= *name++;
89     return hash % NAME_HASH_SIZE;
90 }
91
92 /* allocate a name for an object */
93 static struct object_name *alloc_name( const WCHAR *name, size_t len )
94 {
95     struct object_name *ptr;
96
97     if ((ptr = mem_alloc( sizeof(*ptr) + len - sizeof(ptr->name) )))
98     {
99         ptr->len = len;
100         memcpy( ptr->name, name, len );
101     }
102     return ptr;
103 }
104
105 /* free the name of an object */
106 static void free_name( struct object *obj )
107 {
108     struct object_name *ptr = obj->name;
109     if (ptr->next) ptr->next->prev = ptr->prev;
110     if (ptr->prev) ptr->prev->next = ptr->next;
111     else
112     {
113         int hash;
114         for (hash = 0; hash < NAME_HASH_SIZE; hash++)
115             if (names[hash] == ptr)
116             {
117                 names[hash] = ptr->next;
118                 break;
119             }
120     }
121     free( ptr );
122 }
123
124 /* set the name of an existing object */
125 static void set_object_name( struct object *obj, struct object_name *ptr )
126 {
127     int hash = get_name_hash( ptr->name, ptr->len );
128
129     if ((ptr->next = names[hash]) != NULL) ptr->next->prev = ptr;
130     ptr->obj = obj;
131     ptr->prev = NULL;
132     names[hash] = ptr;
133     assert( !obj->name );
134     obj->name = ptr;
135 }
136
137 /* allocate and initialize an object */
138 /* if the function fails the fd is closed */
139 void *alloc_object( const struct object_ops *ops, int fd )
140 {
141     struct object *obj = mem_alloc( ops->size );
142     if (obj)
143     {
144         obj->refcount = 1;
145         obj->fd       = fd;
146         obj->select   = -1;
147         obj->ops      = ops;
148         obj->head     = NULL;
149         obj->tail     = NULL;
150         obj->name     = NULL;
151         if ((fd != -1) && (add_select_user( obj ) == -1))
152         {
153             close( fd );
154             free( obj );
155             return NULL;
156         }
157 #ifdef DEBUG_OBJECTS
158         obj->prev = NULL;
159         if ((obj->next = first) != NULL) obj->next->prev = obj;
160         first = obj;
161 #endif
162         return obj;
163     }
164     if (fd != -1) close( fd );
165     return NULL;
166 }
167
168 void *create_named_object( const struct object_ops *ops, const WCHAR *name, size_t len )
169 {
170     struct object *obj;
171     struct object_name *name_ptr;
172
173     if (!name || !len) return alloc_object( ops, -1 );
174     if (!(name_ptr = alloc_name( name, len ))) return NULL;
175
176     if ((obj = find_object( name_ptr->name, name_ptr->len )))
177     {
178         free( name_ptr );  /* we no longer need it */
179         if (obj->ops == ops)
180         {
181             set_error( STATUS_OBJECT_NAME_COLLISION );
182             return obj;
183         }
184         set_error( STATUS_OBJECT_TYPE_MISMATCH );
185         return NULL;
186     }
187     if ((obj = alloc_object( ops, -1 )))
188     {
189         set_object_name( obj, name_ptr );
190         clear_error();
191     }
192     else free( name_ptr );
193     return obj;
194 }
195
196 /* dump the name of an object to stderr */
197 void dump_object_name( struct object *obj )
198 {
199     if (!obj->name) fprintf( stderr, "name=\"\"" );
200     else
201     {
202         fprintf( stderr, "name=L\"" );
203         dump_strW( obj->name->name, obj->name->len/sizeof(WCHAR), stderr, "\"\"" );
204         fputc( '\"', stderr );
205     }
206 }
207
208 /* grab an object (i.e. increment its refcount) and return the object */
209 struct object *grab_object( void *ptr )
210 {
211     struct object *obj = (struct object *)ptr;
212     assert( obj->refcount < INT_MAX );
213     obj->refcount++;
214     return obj;
215 }
216
217 /* release an object (i.e. decrement its refcount) */
218 void release_object( void *ptr )
219 {
220     struct object *obj = (struct object *)ptr;
221     assert( obj->refcount );
222     if (!--obj->refcount)
223     {
224         /* if the refcount is 0, nobody can be in the wait queue */
225         assert( !obj->head );
226         assert( !obj->tail );
227         obj->ops->destroy( obj );
228         if (obj->name) free_name( obj );
229         if (obj->select != -1) remove_select_user( obj );
230         if (obj->fd != -1) close( obj->fd );
231 #ifdef DEBUG_OBJECTS
232         if (obj->next) obj->next->prev = obj->prev;
233         if (obj->prev) obj->prev->next = obj->next;
234         else first = obj->next;
235         memset( obj, 0xaa, obj->ops->size );
236 #endif
237         free( obj );
238     }
239 }
240
241 /* find an object by its name; the refcount is incremented */
242 struct object *find_object( const WCHAR *name, size_t len )
243 {
244     struct object_name *ptr;
245
246     if (!name || !len) return NULL;
247     for (ptr = names[ get_name_hash( name, len ) ]; ptr; ptr = ptr->next)
248     {
249         if (ptr->len != len) continue;
250         if (!memcmp( ptr->name, name, len )) return grab_object( ptr->obj );
251     }
252     return NULL;
253 }
254
255 /* functions for unimplemented/default object operations */
256
257 int no_add_queue( struct object *obj, struct wait_queue_entry *entry )
258 {
259     set_error( STATUS_OBJECT_TYPE_MISMATCH );
260     return 0;
261 }
262
263 int no_satisfied( struct object *obj, struct thread *thread )
264 {
265     return 0;  /* not abandoned */
266 }
267
268 int no_get_fd( struct object *obj )
269 {
270     set_error( STATUS_OBJECT_TYPE_MISMATCH );
271     return -1;
272 }
273
274 int no_flush( struct object *obj )
275 {
276     set_error( STATUS_OBJECT_TYPE_MISMATCH );
277     return 0;
278 }
279
280 int no_get_file_info( struct object *obj, struct get_file_info_reply *info, int *flags )
281 {
282     set_error( STATUS_OBJECT_TYPE_MISMATCH );
283     *flags = 0;
284     return FD_TYPE_INVALID;
285 }
286
287 void no_destroy( struct object *obj )
288 {
289 }
290
291 /* default add_queue() routine for objects that poll() on an fd */
292 int default_poll_add_queue( struct object *obj, struct wait_queue_entry *entry )
293 {
294     if (!obj->head)  /* first on the queue */
295         set_select_events( obj, obj->ops->get_poll_events( obj ) );
296     add_queue( obj, entry );
297     return 1;
298 }
299
300 /* default remove_queue() routine for objects that poll() on an fd */
301 void default_poll_remove_queue( struct object *obj, struct wait_queue_entry *entry )
302 {
303     grab_object(obj);
304     remove_queue( obj, entry );
305     if (!obj->head)  /* last on the queue is gone */
306         set_select_events( obj, 0 );
307     release_object( obj );
308 }
309
310 /* default signaled() routine for objects that poll() on an fd */
311 int default_poll_signaled( struct object *obj, struct thread *thread )
312 {
313     int events = obj->ops->get_poll_events( obj );
314
315     if (check_select_events( obj->fd, events ))
316     {
317         /* stop waiting on select() if we are signaled */
318         set_select_events( obj, 0 );
319         return 1;
320     }
321     /* restart waiting on select() if we are no longer signaled */
322     if (obj->head) set_select_events( obj, events );
323     return 0;
324 }
325
326 /* default handler for poll() events */
327 void default_poll_event( struct object *obj, int event )
328 {
329     /* an error occurred, stop polling this fd to avoid busy-looping */
330     if (event & (POLLERR | POLLHUP)) set_select_events( obj, -1 );
331     wake_up( obj, 0 );
332 }