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