Added DebugBreak.
[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
8 #include <assert.h>
9 #include <limits.h>
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <string.h>
13
14 #include "winerror.h"
15 #include "thread.h"
16
17 int debug_level = 0;
18
19 struct object_name
20 {
21     struct object_name *next;
22     struct object      *obj;
23     int                 len;
24     char                name[1];
25 };
26
27 #define NAME_HASH_SIZE 37
28
29 static struct object_name *names[NAME_HASH_SIZE];
30
31 #ifdef DEBUG_OBJECTS
32 static struct object *first;
33
34 void dump_objects(void)
35 {
36     struct object *ptr = first;
37     while (ptr)
38     {
39         fprintf( stderr, "%p:%d: ", ptr, ptr->refcount );
40         ptr->ops->dump( ptr, 1 );
41         ptr = ptr->next;
42     }
43 }
44 #endif
45
46 /*****************************************************************/
47
48 void *mem_alloc( size_t size )
49 {
50     void *ptr = malloc( size );
51     if (ptr) memset( ptr, 0x55, size );
52     else if (current) SET_ERROR( ERROR_OUTOFMEMORY );
53     return ptr;
54 }
55
56 /*****************************************************************/
57
58 static int get_name_hash( const char *name )
59 {
60     int hash = 0;
61     while (*name) hash ^= *name++;
62     return hash % NAME_HASH_SIZE;
63 }
64
65 static struct object_name *add_name( struct object *obj, const char *name )
66 {
67     struct object_name *ptr;
68     int hash = get_name_hash( name );
69     int len = strlen( name );
70
71     if (!(ptr = (struct object_name *)mem_alloc( sizeof(*ptr) + len )))
72         return NULL;
73     ptr->next = names[hash];
74     ptr->obj  = obj;
75     ptr->len  = len;
76     strcpy( ptr->name, name );
77     names[hash] = ptr;
78     return ptr;
79 }
80
81 static void free_name( struct object *obj )
82 {
83     int hash = get_name_hash( obj->name->name );
84     struct object_name **pptr = &names[hash];
85     while (*pptr && *pptr != obj->name) pptr = &(*pptr)->next;
86     assert( *pptr );
87     *pptr = (*pptr)->next;
88     free( obj->name );
89 }
90
91 /* initialize an already allocated object */
92 /* return 1 if OK, 0 on error */
93 int init_object( struct object *obj, const struct object_ops *ops,
94                  const char *name )
95 {
96     obj->refcount = 1;
97     obj->ops      = ops;
98     obj->head     = NULL;
99     obj->tail     = NULL;
100     if (!name) obj->name = NULL;
101     else if (!(obj->name = add_name( obj, name ))) return 0;
102 #ifdef DEBUG_OBJECTS
103     obj->prev = NULL;
104     if ((obj->next = first) != NULL) obj->next->prev = obj;
105     first = obj;
106 #endif
107     return 1;
108 }
109
110 /* allocate and initialize an object */
111 void *alloc_object( size_t size, const struct object_ops *ops, const char *name )
112 {
113     struct object *obj = mem_alloc( size );
114     if (obj) init_object( obj, ops, name );
115     return obj;
116 }
117
118 struct object *create_named_object( const char *name, const struct object_ops *ops, size_t size )
119 {
120     struct object *obj;
121     if ((obj = find_object( name )))
122     {
123         if (obj->ops == ops)
124         {
125             SET_ERROR( ERROR_ALREADY_EXISTS );
126             return obj;
127         }
128         SET_ERROR( ERROR_INVALID_HANDLE );
129         return NULL;
130     }
131     if (!(obj = mem_alloc( size ))) return NULL;
132     if (!init_object( obj, ops, name ))
133     {
134         free( obj );
135         return NULL;
136     }
137     CLEAR_ERROR();
138     return obj;
139 }
140
141 /* return a pointer to the object name, or to an empty string */
142 const char *get_object_name( struct object *obj )
143 {
144     if (!obj->name) return "";
145     return obj->name->name;
146 }
147
148 /* grab an object (i.e. increment its refcount) and return the object */
149 struct object *grab_object( void *ptr )
150 {
151     struct object *obj = (struct object *)ptr;
152     assert( obj->refcount < INT_MAX );
153     obj->refcount++;
154     return obj;
155 }
156
157 /* release an object (i.e. decrement its refcount) */
158 void release_object( void *ptr )
159 {
160     struct object *obj = (struct object *)ptr;
161     assert( obj->refcount );
162     if (!--obj->refcount)
163     {
164         /* if the refcount is 0, nobody can be in the wait queue */
165         assert( !obj->head );
166         assert( !obj->tail );
167         if (obj->name) free_name( obj );
168 #ifdef DEBUG_OBJECTS
169         if (obj->next) obj->next->prev = obj->prev;
170         if (obj->prev) obj->prev->next = obj->next;
171         else first = obj->next;
172 #endif
173         obj->ops->destroy( obj );
174     }
175 }
176
177 /* find an object by its name; the refcount is incremented */
178 struct object *find_object( const char *name )
179 {
180     struct object_name *ptr;
181     if (!name) return NULL;
182     ptr = names[ get_name_hash( name ) ];
183     while (ptr && strcmp( ptr->name, name )) ptr = ptr->next;
184     if (!ptr) return NULL;
185     return grab_object( ptr->obj );
186 }
187
188 /* functions for unimplemented object operations */
189
190 int no_add_queue( struct object *obj, struct wait_queue_entry *entry )
191 {
192     SET_ERROR( ERROR_INVALID_HANDLE );
193     return 0;
194 }
195
196 int no_satisfied( struct object *obj, struct thread *thread )
197 {
198     return 0;  /* not abandoned */
199 }
200
201 int no_read_fd( struct object *obj )
202 {
203     SET_ERROR( ERROR_INVALID_HANDLE );
204     return -1;
205 }
206
207 int no_write_fd( struct object *obj )
208 {
209     SET_ERROR( ERROR_INVALID_HANDLE );
210     return -1;
211 }
212
213 int no_flush( struct object *obj )
214 {
215     SET_ERROR( ERROR_INVALID_HANDLE );
216     return 0;
217 }
218
219 int no_get_file_info( struct object *obj, struct get_file_info_reply *info )
220 {
221     SET_ERROR( ERROR_INVALID_HANDLE );
222     return 0;
223 }
224
225 void default_select_event( int event, void *private )
226 {
227     struct object *obj = (struct object *)private;
228     assert( obj );
229     wake_up( obj, 0 );
230 }