blob: 415bb3d6ef859991a08a24c3a7a98be9b924699b [file] [log] [blame]
Alexandre Julliard642d3131998-07-12 19:29:36 +00001/*
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>
Alexandre Julliard767e6f61998-08-09 12:47:43 +00009#include <limits.h>
Alexandre Julliard642d3131998-07-12 19:29:36 +000010#include <stdlib.h>
11#include <string.h>
12
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000013#include "winerror.h"
Alexandre Julliard642d3131998-07-12 19:29:36 +000014#include "server.h"
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000015#include "server/thread.h"
Alexandre Julliard767e6f61998-08-09 12:47:43 +000016
17int debug_level = 0;
Alexandre Julliard642d3131998-07-12 19:29:36 +000018
19struct 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
29static struct object_name *names[NAME_HASH_SIZE];
30
31/*****************************************************************/
32
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000033void *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
Alexandre Julliard642d3131998-07-12 19:29:36 +000043static 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
50static 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
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000056 if (!(ptr = (struct object_name *)mem_alloc( sizeof(*ptr) + len )))
Alexandre Julliard642d3131998-07-12 19:29:36 +000057 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
66static 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 */
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000077/* return 1 if OK, 0 on error */
78int init_object( struct object *obj, const struct object_ops *ops,
79 const char *name )
Alexandre Julliard642d3131998-07-12 19:29:36 +000080{
81 obj->refcount = 1;
82 obj->ops = ops;
Alexandre Julliard85ed45e1998-08-22 19:03:56 +000083 obj->head = NULL;
84 obj->tail = NULL;
Alexandre Julliard642d3131998-07-12 19:29:36 +000085 if (!name) obj->name = NULL;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +000086 else if (!(obj->name = add_name( obj, name ))) return 0;
87 return 1;
88}
89
90struct 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;
Alexandre Julliard642d3131998-07-12 19:29:36 +0000111}
112
Alexandre Julliard767e6f61998-08-09 12:47:43 +0000113/* grab an object (i.e. increment its refcount) and return the object */
114struct object *grab_object( void *ptr )
115{
116 struct object *obj = (struct object *)ptr;
117 assert( obj->refcount < INT_MAX );
118 obj->refcount++;
119 return obj;
120}
121
122/* release an object (i.e. decrement its refcount) */
Alexandre Julliard642d3131998-07-12 19:29:36 +0000123void release_object( void *ptr )
124{
125 struct object *obj = (struct object *)ptr;
126 assert( obj->refcount );
127 if (!--obj->refcount)
128 {
Alexandre Julliard85ed45e1998-08-22 19:03:56 +0000129 /* if the refcount is 0, nobody can be in the wait queue */
130 assert( !obj->head );
131 assert( !obj->tail );
Alexandre Julliard642d3131998-07-12 19:29:36 +0000132 if (obj->name) free_name( obj );
133 obj->ops->destroy( obj );
134 }
135}
136
137/* find an object by its name; the refcount is incremented */
138struct object *find_object( const char *name )
139{
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000140 struct object_name *ptr;
141 if (!name) return NULL;
142 ptr = names[ get_name_hash( name ) ];
Alexandre Julliard642d3131998-07-12 19:29:36 +0000143 while (ptr && strcmp( ptr->name, name )) ptr = ptr->next;
144 if (!ptr) return NULL;
Alexandre Julliardd30dfd21998-09-27 18:28:36 +0000145 return grab_object( ptr->obj );
Alexandre Julliard642d3131998-07-12 19:29:36 +0000146}
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000147
148/* functions for unimplemented object operations */
149
150int no_satisfied( struct object *obj, struct thread *thread )
151{
152 return 0; /* not abandoned */
153}
154
155int no_read_fd( struct object *obj )
156{
157 SET_ERROR( ERROR_INVALID_HANDLE );
158 return -1;
159}
160
161int no_write_fd( struct object *obj )
162{
163 SET_ERROR( ERROR_INVALID_HANDLE );
164 return -1;
165}
166
167int no_flush( struct object *obj )
168{
169 SET_ERROR( ERROR_INVALID_HANDLE );
170 return 0;
171}
172
173void default_select_event( int fd, int event, void *private )
174{
175 struct object *obj = (struct object *)private;
176 assert( obj );
177 wake_up( obj, 0 );
178}