Changed how list of loadable MCI drivers is obtained.
[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 <string.h>
12
13 #include "winerror.h"
14 #include "server.h"
15 #include "server/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 /*****************************************************************/
32
33 void *mem_alloc( size_t size )
34 {
35     void *ptr = malloc( size );
36     if (ptr) memset( ptr, 0x55, size );
37     else if (current) SET_ERROR( ERROR_OUTOFMEMORY );
38     return ptr;
39 }
40
41 /*****************************************************************/
42
43 static int get_name_hash( const char *name )
44 {
45     int hash = 0;
46     while (*name) hash ^= *name++;
47     return hash % NAME_HASH_SIZE;
48 }
49
50 static struct object_name *add_name( struct object *obj, const char *name )
51 {
52     struct object_name *ptr;
53     int hash = get_name_hash( name );
54     int len = strlen( name );
55
56     if (!(ptr = (struct object_name *)mem_alloc( sizeof(*ptr) + len )))
57         return NULL;
58     ptr->next = names[hash];
59     ptr->obj  = obj;
60     ptr->len  = len;
61     strcpy( ptr->name, name );
62     names[hash] = ptr;
63     return ptr;
64 }
65
66 static void free_name( struct object *obj )
67 {
68     int hash = get_name_hash( obj->name->name );
69     struct object_name **pptr = &names[hash];
70     while (*pptr && *pptr != obj->name) pptr = &(*pptr)->next;
71     assert( *pptr );
72     *pptr = (*pptr)->next;
73     free( obj->name );
74 }
75
76 /* initialize an already allocated object */
77 /* return 1 if OK, 0 on error */
78 int init_object( struct object *obj, const struct object_ops *ops,
79                  const char *name )
80 {
81     obj->refcount = 1;
82     obj->ops      = ops;
83     obj->head     = NULL;
84     obj->tail     = NULL;
85     if (!name) obj->name = NULL;
86     else if (!(obj->name = add_name( obj, name ))) return 0;
87     return 1;
88 }
89
90 struct object *create_named_object( const char *name, const struct object_ops *ops, size_t size )
91 {
92     struct object *obj;
93     if ((obj = find_object( name )))
94     {
95         if (obj->ops == ops)
96         {
97             SET_ERROR( ERROR_ALREADY_EXISTS );
98             return obj;
99         }
100         SET_ERROR( ERROR_INVALID_HANDLE );
101         return NULL;
102     }
103     if (!(obj = mem_alloc( size ))) return NULL;
104     if (!init_object( obj, ops, name ))
105     {
106         free( obj );
107         return NULL;
108     }
109     CLEAR_ERROR();
110     return obj;
111 }
112
113 /* return a pointer to the object name, or to an empty string */
114 const char *get_object_name( struct object *obj )
115 {
116     if (!obj->name) return "";
117     return obj->name->name;
118 }
119
120 /* grab an object (i.e. increment its refcount) and return the object */
121 struct object *grab_object( void *ptr )
122 {
123     struct object *obj = (struct object *)ptr;
124     assert( obj->refcount < INT_MAX );
125     obj->refcount++;
126     return obj;
127 }
128
129 /* release an object (i.e. decrement its refcount) */
130 void release_object( void *ptr )
131 {
132     struct object *obj = (struct object *)ptr;
133     assert( obj->refcount );
134     if (!--obj->refcount)
135     {
136         /* if the refcount is 0, nobody can be in the wait queue */
137         assert( !obj->head );
138         assert( !obj->tail );
139         if (obj->name) free_name( obj );
140         obj->ops->destroy( obj );
141     }
142 }
143
144 /* find an object by its name; the refcount is incremented */
145 struct object *find_object( const char *name )
146 {
147     struct object_name *ptr;
148     if (!name) return NULL;
149     ptr = names[ get_name_hash( name ) ];
150     while (ptr && strcmp( ptr->name, name )) ptr = ptr->next;
151     if (!ptr) return NULL;
152     return grab_object( ptr->obj );
153 }
154
155 /* functions for unimplemented object operations */
156
157 int no_add_queue( struct object *obj, struct wait_queue_entry *entry )
158 {
159     SET_ERROR( ERROR_INVALID_HANDLE );
160     return 0;
161 }
162
163 int no_satisfied( struct object *obj, struct thread *thread )
164 {
165     return 0;  /* not abandoned */
166 }
167
168 int no_read_fd( struct object *obj )
169 {
170     SET_ERROR( ERROR_INVALID_HANDLE );
171     return -1;
172 }
173
174 int no_write_fd( struct object *obj )
175 {
176     SET_ERROR( ERROR_INVALID_HANDLE );
177     return -1;
178 }
179
180 int no_flush( struct object *obj )
181 {
182     SET_ERROR( ERROR_INVALID_HANDLE );
183     return 0;
184 }
185
186 int no_get_file_info( struct object *obj, struct get_file_info_reply *info )
187 {
188     SET_ERROR( ERROR_INVALID_HANDLE );
189     return 0;
190 }
191
192 void default_select_event( int fd, int event, void *private )
193 {
194     struct object *obj = (struct object *)private;
195     assert( obj );
196     wake_up( obj, 0 );
197 }