Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Server-side pipe management |
| 3 | * |
| 4 | * Copyright (C) 1998 Alexandre Julliard |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 5 | * Copyright (C) 2001 Mike McCormack |
| 6 | * |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 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 | * |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 21 | * TODO: |
| 22 | * improve error handling |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 23 | */ |
| 24 | |
| 25 | #include "config.h" |
Alexandre Julliard | 5769d1d | 2002-04-26 19:05:15 +0000 | [diff] [blame] | 26 | #include "wine/port.h" |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 27 | |
| 28 | #include <assert.h> |
| 29 | #include <fcntl.h> |
| 30 | #include <string.h> |
| 31 | #include <stdio.h> |
| 32 | #include <stdlib.h> |
| 33 | #include <sys/time.h> |
| 34 | #include <sys/types.h> |
| 35 | #include <sys/socket.h> |
| 36 | #include <time.h> |
| 37 | #include <unistd.h> |
| 38 | |
| 39 | #include "winbase.h" |
| 40 | |
| 41 | #include "handle.h" |
| 42 | #include "thread.h" |
| 43 | #include "request.h" |
| 44 | |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 45 | enum pipe_state |
| 46 | { |
| 47 | ps_none, |
| 48 | ps_idle_server, |
| 49 | ps_wait_open, |
| 50 | ps_wait_connect, |
| 51 | ps_connected_server, |
| 52 | ps_connected_client, |
| 53 | ps_disconnected |
| 54 | }; |
| 55 | |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 56 | struct named_pipe; |
| 57 | |
| 58 | struct pipe_user |
| 59 | { |
| 60 | struct object obj; |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 61 | enum pipe_state state; |
| 62 | struct pipe_user *other; |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 63 | struct named_pipe *pipe; |
| 64 | struct pipe_user *next; |
| 65 | struct pipe_user *prev; |
Marcus Meissner | 93c3fae | 2002-01-12 21:16:13 +0000 | [diff] [blame] | 66 | struct thread *thread; |
Mike McCormack | 309ed4e | 2001-11-07 20:14:45 +0000 | [diff] [blame] | 67 | void *func; |
| 68 | void *overlapped; |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 69 | }; |
| 70 | |
| 71 | struct named_pipe |
| 72 | { |
| 73 | struct object obj; /* object header */ |
| 74 | unsigned int pipemode; |
| 75 | unsigned int maxinstances; |
| 76 | unsigned int outsize; |
| 77 | unsigned int insize; |
| 78 | unsigned int timeout; |
| 79 | struct pipe_user *users; |
| 80 | }; |
| 81 | |
| 82 | static void named_pipe_dump( struct object *obj, int verbose ); |
| 83 | static void named_pipe_destroy( struct object *obj); |
| 84 | |
| 85 | static const struct object_ops named_pipe_ops = |
| 86 | { |
| 87 | sizeof(struct named_pipe), /* size */ |
| 88 | named_pipe_dump, /* dump */ |
| 89 | no_add_queue, /* add_queue */ |
| 90 | NULL, /* remove_queue */ |
| 91 | NULL, /* signaled */ |
| 92 | NULL, /* satisfied */ |
| 93 | NULL, /* get_poll_events */ |
| 94 | NULL, /* poll_event */ |
| 95 | no_get_fd, /* get_fd */ |
| 96 | no_flush, /* flush */ |
| 97 | no_get_file_info, /* get_file_info */ |
Mike McCormack | 6f011c0 | 2001-12-20 00:07:05 +0000 | [diff] [blame] | 98 | NULL, /* queue_async */ |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 99 | named_pipe_destroy /* destroy */ |
| 100 | }; |
| 101 | |
| 102 | static void pipe_user_dump( struct object *obj, int verbose ); |
| 103 | static void pipe_user_destroy( struct object *obj); |
| 104 | static int pipe_user_get_fd( struct object *obj ); |
Martin Wilck | 88cd32b | 2002-01-09 20:30:51 +0000 | [diff] [blame] | 105 | static int pipe_user_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags ); |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 106 | |
| 107 | static const struct object_ops pipe_user_ops = |
| 108 | { |
| 109 | sizeof(struct pipe_user), /* size */ |
| 110 | pipe_user_dump, /* dump */ |
| 111 | default_poll_add_queue, /* add_queue */ |
| 112 | default_poll_remove_queue, /* remove_queue */ |
| 113 | default_poll_signaled, /* signaled */ |
| 114 | no_satisfied, /* satisfied */ |
| 115 | NULL, /* get_poll_events */ |
| 116 | default_poll_event, /* poll_event */ |
| 117 | pipe_user_get_fd, /* get_fd */ |
| 118 | no_flush, /* flush */ |
Alexandre Julliard | 646d621 | 2001-10-05 19:45:45 +0000 | [diff] [blame] | 119 | pipe_user_get_info, /* get_file_info */ |
Mike McCormack | 6f011c0 | 2001-12-20 00:07:05 +0000 | [diff] [blame] | 120 | NULL, /* queue_async */ |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 121 | pipe_user_destroy /* destroy */ |
| 122 | }; |
| 123 | |
| 124 | static void named_pipe_dump( struct object *obj, int verbose ) |
| 125 | { |
| 126 | struct named_pipe *pipe = (struct named_pipe *)obj; |
| 127 | assert( obj->ops == &named_pipe_ops ); |
| 128 | fprintf( stderr, "named pipe %p\n" ,pipe); |
| 129 | } |
| 130 | |
| 131 | static void pipe_user_dump( struct object *obj, int verbose ) |
| 132 | { |
| 133 | struct pipe_user *user = (struct pipe_user *)obj; |
| 134 | assert( obj->ops == &pipe_user_ops ); |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 135 | fprintf( stderr, "named pipe user %p (state %d)\n", user, user->state ); |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 136 | } |
| 137 | |
| 138 | static void named_pipe_destroy( struct object *obj) |
| 139 | { |
| 140 | struct named_pipe *pipe = (struct named_pipe *)obj; |
| 141 | assert( !pipe->users ); |
| 142 | } |
| 143 | |
Mike McCormack | 309ed4e | 2001-11-07 20:14:45 +0000 | [diff] [blame] | 144 | static void notify_waiter( struct pipe_user *user, unsigned int status) |
| 145 | { |
| 146 | if(user->thread && user->func && user->overlapped) |
| 147 | { |
| 148 | /* queue a system APC, to notify a waiting thread */ |
| 149 | thread_queue_apc(user->thread,NULL,user->func, |
| 150 | APC_ASYNC,1,2,user->overlapped,status); |
| 151 | } |
Marcus Meissner | 93c3fae | 2002-01-12 21:16:13 +0000 | [diff] [blame] | 152 | if (user->thread) release_object(user->thread); |
Mike McCormack | 309ed4e | 2001-11-07 20:14:45 +0000 | [diff] [blame] | 153 | user->thread = NULL; |
| 154 | user->func = NULL; |
| 155 | user->overlapped=NULL; |
| 156 | } |
| 157 | |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 158 | static void pipe_user_destroy( struct object *obj) |
| 159 | { |
| 160 | struct pipe_user *user = (struct pipe_user *)obj; |
| 161 | |
| 162 | assert( obj->ops == &pipe_user_ops ); |
| 163 | |
Mike McCormack | 309ed4e | 2001-11-07 20:14:45 +0000 | [diff] [blame] | 164 | if(user->overlapped) |
| 165 | notify_waiter(user,STATUS_HANDLES_CLOSED); |
| 166 | |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 167 | if(user->other) |
| 168 | { |
| 169 | close(user->other->obj.fd); |
| 170 | user->other->obj.fd = -1; |
| 171 | switch(user->other->state) |
| 172 | { |
| 173 | case ps_connected_server: |
| 174 | user->other->state = ps_idle_server; |
| 175 | break; |
| 176 | case ps_connected_client: |
| 177 | user->other->state = ps_disconnected; |
| 178 | break; |
| 179 | default: |
| 180 | fprintf(stderr,"connected pipe has strange state %d!\n", |
| 181 | user->other->state); |
| 182 | } |
| 183 | user->other->other=NULL; |
| 184 | user->other = NULL; |
| 185 | } |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 186 | |
| 187 | /* remove user from pipe's user list */ |
| 188 | if (user->next) user->next->prev = user->prev; |
| 189 | if (user->prev) user->prev->next = user->next; |
| 190 | else user->pipe->users = user->next; |
Marcus Meissner | 93c3fae | 2002-01-12 21:16:13 +0000 | [diff] [blame] | 191 | if (user->thread) release_object(user->thread); |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 192 | release_object(user->pipe); |
| 193 | } |
| 194 | |
| 195 | static int pipe_user_get_fd( struct object *obj ) |
| 196 | { |
| 197 | struct pipe_user *user = (struct pipe_user *)obj; |
| 198 | assert( obj->ops == &pipe_user_ops ); |
| 199 | return user->obj.fd; |
| 200 | } |
| 201 | |
Martin Wilck | 88cd32b | 2002-01-09 20:30:51 +0000 | [diff] [blame] | 202 | static int pipe_user_get_info( struct object *obj, struct get_file_info_reply *reply, int *flags ) |
Alexandre Julliard | 646d621 | 2001-10-05 19:45:45 +0000 | [diff] [blame] | 203 | { |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 204 | if (reply) |
Alexandre Julliard | 646d621 | 2001-10-05 19:45:45 +0000 | [diff] [blame] | 205 | { |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 206 | reply->type = FILE_TYPE_PIPE; |
| 207 | reply->attr = 0; |
| 208 | reply->access_time = 0; |
| 209 | reply->write_time = 0; |
| 210 | reply->size_high = 0; |
| 211 | reply->size_low = 0; |
| 212 | reply->links = 0; |
| 213 | reply->index_high = 0; |
| 214 | reply->index_low = 0; |
| 215 | reply->serial = 0; |
Alexandre Julliard | 646d621 | 2001-10-05 19:45:45 +0000 | [diff] [blame] | 216 | } |
Martin Wilck | 88cd32b | 2002-01-09 20:30:51 +0000 | [diff] [blame] | 217 | *flags = 0; |
Alexandre Julliard | 646d621 | 2001-10-05 19:45:45 +0000 | [diff] [blame] | 218 | return FD_TYPE_DEFAULT; |
| 219 | } |
| 220 | |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 221 | static struct named_pipe *create_named_pipe( const WCHAR *name, size_t len ) |
| 222 | { |
| 223 | struct named_pipe *pipe; |
| 224 | |
| 225 | if ((pipe = create_named_object( &named_pipe_ops, name, len ))) |
| 226 | { |
| 227 | if (get_error() != STATUS_OBJECT_NAME_COLLISION) |
| 228 | { |
| 229 | /* initialize it if it didn't already exist */ |
| 230 | pipe->users = 0; |
| 231 | } |
| 232 | } |
| 233 | return pipe; |
| 234 | } |
| 235 | |
| 236 | static struct pipe_user *get_pipe_user_obj( struct process *process, handle_t handle, |
| 237 | unsigned int access ) |
| 238 | { |
| 239 | return (struct pipe_user *)get_handle_obj( process, handle, access, &pipe_user_ops ); |
| 240 | } |
| 241 | |
| 242 | static struct pipe_user *create_pipe_user( struct named_pipe *pipe, int fd ) |
| 243 | { |
| 244 | struct pipe_user *user; |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 245 | |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 246 | user = alloc_object( &pipe_user_ops, fd ); |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 247 | if(!user) |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 248 | return NULL; |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 249 | |
| 250 | user->pipe = pipe; |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 251 | user->state = ps_none; |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 252 | user->other = NULL; |
Mike McCormack | 309ed4e | 2001-11-07 20:14:45 +0000 | [diff] [blame] | 253 | user->thread = NULL; |
| 254 | user->func = NULL; |
| 255 | user->overlapped = NULL; |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 256 | |
| 257 | /* add to list of pipe users */ |
| 258 | if ((user->next = pipe->users)) user->next->prev = user; |
| 259 | user->prev = NULL; |
| 260 | pipe->users = user; |
| 261 | |
| 262 | grab_object(pipe); |
| 263 | |
| 264 | return user; |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 265 | } |
| 266 | |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 267 | static struct pipe_user *find_partner(struct named_pipe *pipe, enum pipe_state state) |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 268 | { |
| 269 | struct pipe_user *x; |
| 270 | |
| 271 | for(x = pipe->users; x; x=x->next) |
| 272 | { |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 273 | if(x->state==state) |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 274 | break; |
| 275 | } |
| 276 | |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 277 | if(!x) |
| 278 | return NULL; |
| 279 | |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 280 | return (struct pipe_user *)grab_object( x ); |
| 281 | } |
| 282 | |
| 283 | DECL_HANDLER(create_named_pipe) |
| 284 | { |
| 285 | struct named_pipe *pipe; |
| 286 | struct pipe_user *user; |
| 287 | |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 288 | reply->handle = 0; |
| 289 | pipe = create_named_pipe( get_req_data(), get_req_data_size() ); |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 290 | if(!pipe) |
| 291 | return; |
| 292 | |
Mike McCormack | f2e7ce7 | 2001-08-27 19:03:42 +0000 | [diff] [blame] | 293 | if (get_error() != STATUS_OBJECT_NAME_COLLISION) |
| 294 | { |
| 295 | pipe->insize = req->insize; |
| 296 | pipe->outsize = req->outsize; |
| 297 | pipe->maxinstances = req->maxinstances; |
| 298 | pipe->timeout = req->timeout; |
| 299 | pipe->pipemode = req->pipemode; |
| 300 | } |
| 301 | |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 302 | user = create_pipe_user (pipe, -1); |
| 303 | |
| 304 | if(user) |
| 305 | { |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 306 | user->state = ps_idle_server; |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 307 | reply->handle = alloc_handle( current->process, user, GENERIC_READ|GENERIC_WRITE, 0 ); |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 308 | release_object( user ); |
| 309 | } |
| 310 | |
| 311 | release_object( pipe ); |
| 312 | } |
| 313 | |
| 314 | DECL_HANDLER(open_named_pipe) |
| 315 | { |
| 316 | struct named_pipe *pipe; |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 317 | |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 318 | reply->handle = 0; |
| 319 | pipe = create_named_pipe( get_req_data(), get_req_data_size() ); |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 320 | if(!pipe) |
| 321 | return; |
| 322 | |
| 323 | if (get_error() == STATUS_OBJECT_NAME_COLLISION) |
| 324 | { |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 325 | struct pipe_user *partner; |
| 326 | |
| 327 | if ((partner = find_partner(pipe, ps_wait_open))) |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 328 | { |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 329 | int fds[2]; |
| 330 | |
| 331 | if(!socketpair(PF_UNIX, SOCK_STREAM, 0, fds)) |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 332 | { |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 333 | struct pipe_user *user; |
| 334 | |
| 335 | if( (user = create_pipe_user (pipe, fds[1])) ) |
| 336 | { |
| 337 | partner->obj.fd = fds[0]; |
Mike McCormack | 309ed4e | 2001-11-07 20:14:45 +0000 | [diff] [blame] | 338 | notify_waiter(partner,STATUS_SUCCESS); |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 339 | partner->state = ps_connected_server; |
| 340 | partner->other = user; |
| 341 | user->state = ps_connected_client; |
| 342 | user->other = partner; |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 343 | reply->handle = alloc_handle( current->process, user, req->access, 0 ); |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 344 | release_object(user); |
| 345 | } |
| 346 | else |
| 347 | { |
| 348 | close(fds[0]); |
| 349 | } |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 350 | } |
| 351 | release_object( partner ); |
| 352 | } |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 353 | else |
| 354 | { |
Ove Kaaven | 705e7d7 | 2001-07-17 00:38:00 +0000 | [diff] [blame] | 355 | set_error(STATUS_PIPE_NOT_AVAILABLE); |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 356 | } |
| 357 | } |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 358 | else |
| 359 | { |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 360 | set_error(STATUS_NO_SUCH_FILE); |
| 361 | } |
| 362 | |
| 363 | release_object(pipe); |
| 364 | } |
| 365 | |
| 366 | DECL_HANDLER(connect_named_pipe) |
| 367 | { |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 368 | struct pipe_user *user, *partner; |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 369 | |
| 370 | user = get_pipe_user_obj(current->process, req->handle, 0); |
| 371 | if(!user) |
| 372 | return; |
| 373 | |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 374 | if( user->state != ps_idle_server ) |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 375 | { |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 376 | set_error(STATUS_PORT_ALREADY_SET); |
| 377 | } |
| 378 | else |
| 379 | { |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 380 | user->state = ps_wait_open; |
Marcus Meissner | 93c3fae | 2002-01-12 21:16:13 +0000 | [diff] [blame] | 381 | user->thread = (struct thread *)grab_object(current); |
Mike McCormack | 309ed4e | 2001-11-07 20:14:45 +0000 | [diff] [blame] | 382 | user->func = req->func; |
| 383 | user->overlapped = req->overlapped; |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 384 | |
| 385 | /* notify all waiters that a pipe just became available */ |
| 386 | while( (partner = find_partner(user->pipe,ps_wait_connect)) ) |
| 387 | { |
Mike McCormack | 309ed4e | 2001-11-07 20:14:45 +0000 | [diff] [blame] | 388 | notify_waiter(partner,STATUS_SUCCESS); |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 389 | release_object(partner); |
| 390 | release_object(partner); |
| 391 | } |
Mike McCormack | de7c300 | 2001-07-10 19:16:49 +0000 | [diff] [blame] | 392 | } |
| 393 | |
| 394 | release_object(user); |
| 395 | } |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 396 | |
| 397 | DECL_HANDLER(wait_named_pipe) |
| 398 | { |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 399 | struct named_pipe *pipe; |
| 400 | |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 401 | pipe = create_named_pipe( get_req_data(), get_req_data_size() ); |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 402 | if( pipe ) |
| 403 | { |
| 404 | /* only wait if the pipe already exists */ |
| 405 | if(get_error() == STATUS_OBJECT_NAME_COLLISION) |
| 406 | { |
| 407 | struct pipe_user *partner; |
| 408 | |
| 409 | set_error(STATUS_SUCCESS); |
| 410 | if( (partner = find_partner(pipe,ps_wait_open)) ) |
| 411 | { |
Mike McCormack | 309ed4e | 2001-11-07 20:14:45 +0000 | [diff] [blame] | 412 | /* this should use notify_waiter, |
| 413 | but no pipe_user object exists now... */ |
| 414 | thread_queue_apc(current,NULL,req->func, |
| 415 | APC_ASYNC,1,2,req->overlapped,STATUS_SUCCESS); |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 416 | release_object(partner); |
| 417 | } |
| 418 | else |
| 419 | { |
| 420 | struct pipe_user *user; |
| 421 | |
| 422 | if( (user = create_pipe_user (pipe, -1)) ) |
| 423 | { |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 424 | user->state = ps_wait_connect; |
Marcus Meissner | 93c3fae | 2002-01-12 21:16:13 +0000 | [diff] [blame] | 425 | user->thread = (struct thread *)grab_object(current); |
Mike McCormack | 309ed4e | 2001-11-07 20:14:45 +0000 | [diff] [blame] | 426 | user->func = req->func; |
| 427 | user->overlapped = req->overlapped; |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 428 | /* don't release it */ |
| 429 | } |
| 430 | } |
| 431 | } |
| 432 | else |
| 433 | { |
| 434 | set_error(STATUS_PIPE_NOT_AVAILABLE); |
| 435 | } |
| 436 | release_object(pipe); |
| 437 | } |
Mike McCormack | bf55457 | 2001-08-23 23:29:20 +0000 | [diff] [blame] | 438 | } |
| 439 | |
| 440 | DECL_HANDLER(disconnect_named_pipe) |
| 441 | { |
| 442 | struct pipe_user *user; |
| 443 | |
| 444 | user = get_pipe_user_obj(current->process, req->handle, 0); |
| 445 | if(!user) |
| 446 | return; |
| 447 | if( (user->state == ps_connected_server) && |
| 448 | (user->other->state == ps_connected_client) ) |
| 449 | { |
| 450 | close(user->other->obj.fd); |
| 451 | user->other->obj.fd = -1; |
| 452 | user->other->state = ps_disconnected; |
| 453 | user->other->other = NULL; |
| 454 | |
| 455 | close(user->obj.fd); |
| 456 | user->obj.fd = -1; |
| 457 | user->state = ps_idle_server; |
| 458 | user->other = NULL; |
| 459 | } |
| 460 | release_object(user); |
| 461 | } |
Mike McCormack | f2e7ce7 | 2001-08-27 19:03:42 +0000 | [diff] [blame] | 462 | |
| 463 | DECL_HANDLER(get_named_pipe_info) |
| 464 | { |
| 465 | struct pipe_user *user; |
| 466 | |
| 467 | user = get_pipe_user_obj(current->process, req->handle, 0); |
| 468 | if(!user) |
| 469 | return; |
| 470 | |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 471 | reply->flags = user->pipe->pipemode; |
| 472 | reply->maxinstances = user->pipe->maxinstances; |
| 473 | reply->insize = user->pipe->insize; |
| 474 | reply->outsize = user->pipe->outsize; |
Mike McCormack | f2e7ce7 | 2001-08-27 19:03:42 +0000 | [diff] [blame] | 475 | |
| 476 | release_object(user); |
| 477 | } |
| 478 | |