named_pipe.c 21.3 KB
Newer Older
1 2 3 4
/*
 * Server-side pipe management
 *
 * Copyright (C) 1998 Alexandre Julliard
5 6
 * Copyright (C) 2001 Mike McCormack
 *
7 8 9 10 11 12 13 14 15 16 17 18 19 20
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
21
 * TODO:
22
 *   message mode
23 24 25
 */

#include "config.h"
26
#include "wine/port.h"
27 28 29 30 31 32 33 34

#include <assert.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
Steven Edwards's avatar
Steven Edwards committed
35
#ifdef HAVE_SYS_SOCKET_H
36
#include <sys/socket.h>
Steven Edwards's avatar
Steven Edwards committed
37
#endif
38 39 40 41 42
#include <time.h>
#include <unistd.h>

#include "winbase.h"

43
#include "file.h"
44 45 46 47
#include "handle.h"
#include "thread.h"
#include "request.h"

48 49 50 51 52 53
enum pipe_state
{
    ps_none,
    ps_idle_server,
    ps_wait_open,
    ps_connected_server,
54 55 56 57 58 59 60 61 62 63
    ps_wait_disconnect,
    ps_disconnected_server,
    ps_wait_connect
};

struct wait_info
{
    struct thread       *thread;
    void                *func;
    void                *overlapped;
64 65
};

66 67
struct named_pipe;

68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
struct pipe_server
{
    struct object        obj;
    struct fd           *fd;
    enum pipe_state      state;
    struct pipe_client  *client;
    struct named_pipe   *pipe;
    struct pipe_server  *next;
    struct pipe_server  *prev;
    struct timeout_user *flush_poll;
    struct event        *event;
    struct wait_info     wait;
};

struct pipe_client
{
    struct object        obj;
    struct fd           *fd;
    struct pipe_server  *server;
    struct wait_info     wait;
};

struct connect_wait
{
    struct wait_info     wait;
    struct connect_wait *next;
94 95 96 97 98 99 100 101 102 103
};

struct named_pipe
{
    struct object       obj;         /* object header */
    unsigned int        pipemode;
    unsigned int        maxinstances;
    unsigned int        outsize;
    unsigned int        insize;
    unsigned int        timeout;
104 105 106
    unsigned int        instances;
    struct pipe_server *servers;
    struct connect_wait *connect_waiters;
107 108 109
};

static void named_pipe_dump( struct object *obj, int verbose );
110
static void named_pipe_destroy( struct object *obj );
111 112 113 114 115 116 117 118 119 120 121 122 123

static const struct object_ops named_pipe_ops =
{
    sizeof(struct named_pipe),    /* size */
    named_pipe_dump,              /* dump */
    no_add_queue,                 /* add_queue */
    NULL,                         /* remove_queue */
    NULL,                         /* signaled */
    NULL,                         /* satisfied */
    no_get_fd,                    /* get_fd */
    named_pipe_destroy            /* destroy */
};

124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
/* common to clients and servers */
static int pipe_end_get_poll_events( struct fd *fd );
static int pipe_end_get_info( struct fd *fd, 
                  struct get_file_info_reply *reply, int *flags );

/* server end functions */
static void pipe_server_dump( struct object *obj, int verbose );
static struct fd *pipe_server_get_fd( struct object *obj );
static void pipe_server_destroy( struct object *obj);
static int pipe_server_flush( struct fd *fd, struct event **event );

static const struct object_ops pipe_server_ops =
{
    sizeof(struct pipe_server),   /* size */
    pipe_server_dump,             /* dump */
    default_fd_add_queue,         /* add_queue */
    default_fd_remove_queue,      /* remove_queue */
    default_fd_signaled,          /* signaled */
    no_satisfied,                 /* satisfied */
    pipe_server_get_fd,           /* get_fd */
    pipe_server_destroy           /* destroy */
};

static const struct fd_ops pipe_server_fd_ops =
{
    pipe_end_get_poll_events,     /* get_poll_events */
    default_poll_event,           /* poll_event */
    pipe_server_flush,            /* flush */
    pipe_end_get_info,            /* get_file_info */
    no_queue_async                /* queue_async */
};
155

156 157 158 159 160
/* client end functions */
static void pipe_client_dump( struct object *obj, int verbose );
static struct fd *pipe_client_get_fd( struct object *obj );
static void pipe_client_destroy( struct object *obj );
static int pipe_client_flush( struct fd *fd, struct event **event );
161

162
static const struct object_ops pipe_client_ops =
163
{
164 165
    sizeof(struct pipe_client),   /* size */
    pipe_client_dump,             /* dump */
166 167 168
    default_fd_add_queue,         /* add_queue */
    default_fd_remove_queue,      /* remove_queue */
    default_fd_signaled,          /* signaled */
169
    no_satisfied,                 /* satisfied */
170 171
    pipe_client_get_fd,           /* get_fd */
    pipe_client_destroy           /* destroy */
172 173
};

174
static const struct fd_ops pipe_client_fd_ops =
175
{
176
    pipe_end_get_poll_events,     /* get_poll_events */
177
    default_poll_event,           /* poll_event */
178 179
    pipe_client_flush,            /* flush */
    pipe_end_get_info,            /* get_file_info */
180
    no_queue_async                /* queue_async */
181 182 183 184
};

static void named_pipe_dump( struct object *obj, int verbose )
{
185
    struct named_pipe *pipe = (struct named_pipe *) obj;
186 187 188 189
    assert( obj->ops == &named_pipe_ops );
    fprintf( stderr, "named pipe %p\n" ,pipe);
}

190 191 192 193 194 195 196 197 198
static void pipe_server_dump( struct object *obj, int verbose )
{
    struct pipe_server *server = (struct pipe_server *) obj;
    assert( obj->ops == &pipe_server_ops );
    fprintf( stderr, "named pipe server %p (state %d)\n",
             server, server->state );
}

static void pipe_client_dump( struct object *obj, int verbose )
199
{
200 201 202 203
    struct pipe_client *client = (struct pipe_client *) obj;
    assert( obj->ops == &pipe_server_ops );
    fprintf( stderr, "named pipe client %p (server state %d)\n",
             client, client->server->state );
204 205 206 207
}

static void named_pipe_destroy( struct object *obj)
{
208 209 210
    struct named_pipe *pipe = (struct named_pipe *) obj;
    assert( !pipe->servers );
    assert( !pipe->instances );
211 212
}

213
static void notify_waiter( struct wait_info *wait, unsigned int status )
214
{
215
    if( wait->thread && wait->func && wait->overlapped )
216 217
    {
        /* queue a system APC, to notify a waiting thread */
218 219
        thread_queue_apc( wait->thread, NULL, wait->func, APC_ASYNC,
                          1, wait->overlapped, (void *)status, NULL );
220
    }
221 222 223 224 225 226 227 228 229
    if( wait->thread ) release_object( wait->thread );
    wait->thread = NULL;
}

static void set_waiter( struct wait_info *wait, void *func, void *ov )
{
    wait->thread = (struct thread *) grab_object( current );
    wait->func = func;
    wait->overlapped = ov;
230 231
}

232
static void notify_connect_waiters( struct named_pipe *pipe )
233
{
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
    struct connect_wait *cw, **x = &pipe->connect_waiters;

    while( *x )
    {
        cw = *x;
        notify_waiter( &cw->wait, STATUS_SUCCESS );
        release_object( pipe );
        *x = cw->next;
        free( cw );
    }
}

static void queue_connect_waiter( struct named_pipe *pipe,
                                  void *func, void *overlapped )
{
    struct connect_wait *waiter;

251
    waiter = mem_alloc( sizeof(*waiter) );
252 253 254 255 256 257 258 259 260 261 262 263 264 265
    if( waiter )
    {
        set_waiter( &waiter->wait, func, overlapped );
        waiter->next = pipe->connect_waiters;
        pipe->connect_waiters = waiter;
        grab_object( pipe );
    }
}

static struct fd *pipe_client_get_fd( struct object *obj )
{
    struct pipe_client *client = (struct pipe_client *) obj;
    if( client->fd )
        return (struct fd *) grab_object( client->fd );
266 267
    set_error( STATUS_PIPE_DISCONNECTED );
    return NULL;
268 269
}

270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
static struct fd *pipe_server_get_fd( struct object *obj )
{
    struct pipe_server *server = (struct pipe_server *) obj;

    switch(server->state)
    {
    case ps_connected_server:
    case ps_wait_disconnect:
        assert( server->fd );
        return (struct fd *) grab_object( server->fd );

    case ps_wait_open:
    case ps_idle_server:
        set_error( STATUS_PIPE_LISTENING );
        break;

    case ps_disconnected_server:
    case ps_wait_connect:
        set_error( STATUS_PIPE_DISCONNECTED );
        break;

    default:
        assert( 0 );
    }
    return NULL;
}


static void notify_empty( struct pipe_server *server )
{
    if( !server->flush_poll )
        return;
    assert( server->state == ps_connected_server );
    assert( server->event );
    remove_timeout_user( server->flush_poll );
    server->flush_poll = NULL;
    set_event( server->event );
    release_object( server->event );
    server->event = NULL;
}

static void do_disconnect( struct pipe_server *server )
{
    /* we may only have a server fd, if the client disconnected */
    if( server->client )
    {
        assert( server->client->server == server );
        assert( server->client->fd );
        release_object( server->client->fd );
        server->client->fd = NULL;
    }
    assert( server->fd );
    release_object( server->fd );
    server->fd = NULL;
}

static void pipe_server_destroy( struct object *obj)
{
    struct pipe_server *server = (struct pipe_server *)obj;

    assert( obj->ops == &pipe_server_ops );

    if( server->fd )
    {
        notify_empty( server );
        do_disconnect( server );
    }

    if( server->client )
    {
        server->client->server = NULL;
        server->client = NULL;
    }

    notify_waiter( &server->wait, STATUS_HANDLES_CLOSED );

    assert( server->pipe->instances );
    server->pipe->instances--;

    /* remove server from pipe's server list */
    if( server->next ) server->next->prev = server->prev;
    if( server->prev ) server->prev->next = server->next;
    else server->pipe->servers = server->next;
    release_object( server->pipe );
}

static void pipe_client_destroy( struct object *obj)
357
{
358 359
    struct pipe_client *client = (struct pipe_client *)obj;
    struct pipe_server *server = client->server;
360

361
    assert( obj->ops == &pipe_client_ops );
362

363
    notify_waiter( &client->wait, STATUS_HANDLES_CLOSED );
364

365
    if( server )
366
    {
367 368 369
        notify_empty( server );

        switch( server->state )
370 371
        {
        case ps_connected_server:
372 373 374 375 376
            /* Don't destroy the server's fd here as we can't
               do a successful flush without it. */
            server->state = ps_wait_disconnect;
            release_object( client->fd );
            client->fd = NULL;
377
            break;
378 379
        case ps_disconnected_server:
            server->state = ps_wait_connect;
380 381
            break;
        default:
382
            assert( 0 );
383
        }
384 385 386
        assert( server->client );
        server->client = NULL;
        client->server = NULL;
387
    }
388
    assert( !client->fd );
389 390
}

391
static int pipe_end_get_poll_events( struct fd *fd )
392 393
{
    return POLLIN | POLLOUT;  /* FIXME */
394 395
}

396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
static int pipe_data_remaining( struct pipe_server *server )
{
    struct pollfd pfd;
    int fd;

    assert( server->client );

    fd = get_unix_fd( server->client->fd );
    if( fd < 0 )
        return 0;
    pfd.fd = fd;
    pfd.events = POLLIN;
    pfd.revents = 0;

    if( 0 > poll( &pfd, 1, 0 ) )
        return 0;
 
    return pfd.revents&POLLIN;
}

static void check_flushed( void *arg )
{
    struct pipe_server *server = (struct pipe_server*) arg;

    assert( server->event );
    if( pipe_data_remaining( server ) )
    {
        struct timeval tv;

        gettimeofday( &tv, 0 );
        add_timeout( &tv, 100 );
        server->flush_poll = add_timeout_user( &tv, check_flushed, server );
    }
    else
        notify_empty( server );
}

static int pipe_server_flush( struct fd *fd, struct event **event )
{
    struct pipe_server *server = get_fd_user( fd );

    if( !server )
        return 0;

    if( server->state != ps_connected_server )
        return 0;

    /* FIXME: if multiple threads flush the same pipe,
              maybe should create a list of processes to notify */
    if( server->flush_poll )
        return 0;

    if( pipe_data_remaining( server ) )
    {
        struct timeval tv;

        /* this kind of sux - 
           there's no unix way to be alerted when a pipe becomes empty */
        server->event = create_event( NULL, 0, 0, 0 );
        if( !server->event )
            return 0;
        gettimeofday( &tv, 0 );
        add_timeout( &tv, 100 );
        server->flush_poll = add_timeout_user( &tv, check_flushed, server );
        *event = server->event;
    }

    return 0; 
}

static int pipe_client_flush( struct fd *fd, struct event **event )
{
    /* FIXME: what do we have to do for this? */
    return 0;
}

static int pipe_end_get_info( struct fd *fd, 
                        struct get_file_info_reply *reply, int *flags )
474
{
475
    if (reply)
476
    {
477 478 479 480 481 482 483 484 485 486
        reply->type        = FILE_TYPE_PIPE;
        reply->attr        = 0;
        reply->access_time = 0;
        reply->write_time  = 0;
        reply->size_high   = 0;
        reply->size_low    = 0;
        reply->links       = 0;
        reply->index_high  = 0;
        reply->index_low   = 0;
        reply->serial      = 0;
487
    }
488
    *flags = 0;
489 490 491
    return FD_TYPE_DEFAULT;
}

492 493 494 495
static struct named_pipe *create_named_pipe( const WCHAR *name, size_t len )
{
    struct named_pipe *pipe;

496 497
    pipe = create_named_object( sync_namespace, &named_pipe_ops, name, len );
    if( pipe )
498
    {
499
        if( get_error() != STATUS_OBJECT_NAME_COLLISION )
500 501
        {
            /* initialize it if it didn't already exist */
502 503 504
            pipe->servers = 0;
            pipe->instances = 0;
            pipe->connect_waiters = NULL;
505 506 507 508 509
        }
    }
    return pipe;
}

510 511 512 513 514 515 516 517 518 519 520 521 522 523 524
static struct named_pipe *open_named_pipe( const WCHAR *name, size_t len )
{
    struct object *obj;

    if ((obj = find_object( sync_namespace, name, len )))
    {
        if (obj->ops == &named_pipe_ops) return (struct named_pipe *)obj;
        release_object( obj );
        set_error( STATUS_OBJECT_TYPE_MISMATCH );
    }
    else set_error( STATUS_OBJECT_NAME_NOT_FOUND );

    return NULL;
}

525 526
static struct pipe_server *get_pipe_server_obj( struct process *process,
                                obj_handle_t handle, unsigned int access )
527
{
528 529 530
    struct object *obj;
    obj = get_handle_obj( process, handle, access, &pipe_server_ops );
    return (struct pipe_server *) obj;
531 532
}

533
static struct pipe_server *create_pipe_server( struct named_pipe *pipe )
534
{
535
    struct pipe_server *server;
536

537 538
    server = alloc_object( &pipe_server_ops );
    if( !server )
539 540
        return NULL;

541 542 543 544 545 546
    server->fd = NULL;
    server->pipe = pipe;
    server->state = ps_none;
    server->client = NULL;
    server->flush_poll = NULL;
    server->wait.thread = NULL;
547

548 549 550 551
    /* add to list of pipe servers */
    if ((server->next = pipe->servers)) server->next->prev = server;
    server->prev = NULL;
    pipe->servers = server;
552

553
    grab_object( pipe );
554

555
    return server;
556 557
}

558
static struct pipe_client *create_pipe_client( struct pipe_server *server )
559
{
560
    struct pipe_client *client;
561

562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580
    client = alloc_object( &pipe_client_ops );
    if( !client )
        return NULL;

    client->fd = NULL;
    client->server = server;
    client->wait.thread = NULL;

    return client;
}

static struct pipe_server *find_server( struct named_pipe *pipe,
                                        enum pipe_state state )
{
    struct pipe_server *x;

    for( x = pipe->servers; x; x = x->next )
        if( x->state == state )
            break;
581

582
    if( !x )
583 584
        return NULL;

585
    return (struct pipe_server *) grab_object( x );
586 587 588 589 590
}

DECL_HANDLER(create_named_pipe)
{
    struct named_pipe *pipe;
591
    struct pipe_server *server;
592

593 594
    reply->handle = 0;
    pipe = create_named_pipe( get_req_data(), get_req_data_size() );
595
    if( !pipe )
596 597
        return;

598
    if( get_error() != STATUS_OBJECT_NAME_COLLISION )
599 600 601 602 603 604 605
    {
        pipe->insize = req->insize;
        pipe->outsize = req->outsize;
        pipe->maxinstances = req->maxinstances;
        pipe->timeout = req->timeout;
        pipe->pipemode = req->pipemode;
    }
606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623
    else
    {
        set_error( 0 );  /* clear the name collision */
        if( pipe->maxinstances <= pipe->instances )
        {
            set_error( STATUS_PIPE_BUSY );
            release_object( pipe );
            return;
        }
        if( ( pipe->maxinstances != req->maxinstances ) ||
            ( pipe->timeout != req->timeout ) ||
            ( pipe->pipemode != req->pipemode ) )
        {
            set_error( STATUS_ACCESS_DENIED );
            release_object( pipe );
            return;
        }
    }
624

625 626
    server = create_pipe_server( pipe );
    if(server)
627
    {
628 629 630 631 632
        server->state = ps_idle_server;
        reply->handle = alloc_handle( current->process, server,
                                      GENERIC_READ|GENERIC_WRITE, 0 );
        server->pipe->instances++;
        release_object( server );
633 634 635 636 637 638 639
    }

    release_object( pipe );
}

DECL_HANDLER(open_named_pipe)
{
640 641
    struct pipe_server *server;
    struct pipe_client *client;
642
    struct named_pipe *pipe;
643
    int fds[2];
644

645
    reply->handle = 0;
646

647 648
    pipe = open_named_pipe( get_req_data(), get_req_data_size() );
    if ( !pipe )
649
    {
650 651 652
        set_error( STATUS_NO_SUCH_FILE );
        return;
    }
653 654 655 656 657 658 659 660

    for( server = pipe->servers; server; server = server->next )
        if( ( server->state==ps_idle_server ) ||
            ( server->state==ps_wait_open ) )
            break;
    release_object( pipe );

    if ( !server )
661 662 663 664
    {
        set_error( STATUS_PIPE_NOT_AVAILABLE );
        return;
    }
665

666 667 668 669
    client = create_pipe_client( server );
    if( client )
    {
        if( !socketpair( PF_UNIX, SOCK_STREAM, 0, fds ) )
670
        {
671 672 673 674 675 676 677
            assert( !client->fd );
            assert( !server->fd );
            client->fd = create_anonymous_fd( &pipe_server_fd_ops,
                                            fds[1], &client->obj );
            server->fd = create_anonymous_fd( &pipe_server_fd_ops,
                                            fds[0], &server->obj );
            if (client->fd && server->fd)
678
            {
679 680 681 682 683 684 685
                if( server->state == ps_wait_open )
                    notify_waiter( &server->wait, STATUS_SUCCESS );
                assert( !server->wait.thread );
                server->state = ps_connected_server;
                server->client = client;
                client->server = server;
                reply->handle = alloc_handle( current->process, client,
686
                                              req->access, req->inherit );
687 688
            }
        }
689 690
        else
            file_set_error();
691

692
        release_object( client );
693
    }
694 695 696 697
}

DECL_HANDLER(connect_named_pipe)
{
698
    struct pipe_server *server;
699

700 701
    server = get_pipe_server_obj(current->process, req->handle, 0);
    if(!server)
702 703
        return;

704
    switch( server->state )
705
    {
706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725
    case ps_idle_server:
    case ps_wait_connect:
        assert( !server->fd );
        server->state = ps_wait_open;
        set_waiter( &server->wait, req->func, req->overlapped );
        notify_connect_waiters( server->pipe );
        break;
    case ps_connected_server:
        assert( server->fd );
        set_error( STATUS_PIPE_CONNECTED );
        break;
    case ps_disconnected_server:
        set_error( STATUS_PIPE_BUSY );
        break;
    case ps_wait_disconnect:
        set_error( STATUS_NO_DATA_DETECTED );
        break;
    default:
        set_error( STATUS_INVALID_HANDLE );
        break;
726 727
    }

728
    release_object(server);
729 730 731 732 733
}

DECL_HANDLER(wait_named_pipe)
{
    struct named_pipe *pipe;
734
    struct pipe_server *server;
735

736
    if (!(pipe = open_named_pipe( get_req_data(), get_req_data_size() )))
737
    {
738 739 740
        set_error( STATUS_PIPE_NOT_AVAILABLE );
        return;
    }
741 742
    server = find_server( pipe, ps_wait_open );
    if( server )
743
    {
744 745 746 747 748
        /* there's already a server waiting for a client to connect */
        struct wait_info wait;
        set_waiter( &wait, req->func, req->overlapped );
        notify_waiter( &wait, STATUS_SUCCESS );
        release_object( server );
749 750
    }
    else
751
        queue_connect_waiter( pipe, req->func, req->overlapped );
752

753
    release_object( pipe );
754
}
755

756 757
DECL_HANDLER(disconnect_named_pipe)
{
758
    struct pipe_server *server;
759

760 761 762
    reply->fd = -1;
    server = get_pipe_server_obj( current->process, req->handle, 0 );
    if( !server )
763
        return;
764
    switch( server->state )
765
    {
766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790
    case ps_connected_server:
        assert( server->fd );
        assert( server->client );
        assert( server->client->fd );

        notify_empty( server );
        notify_waiter( &server->client->wait, STATUS_PIPE_DISCONNECTED );

        /* Dump the client and server fds, but keep the pointers
           around - client loses all waiting data */
        server->state = ps_disconnected_server;
        do_disconnect( server );
        reply->fd = flush_cached_fd( current->process, req->handle );
        break;

    case ps_wait_disconnect:
        assert( !server->client );
        assert( server->fd );
        do_disconnect( server );
        server->state = ps_wait_connect;
        reply->fd = flush_cached_fd( current->process, req->handle );
        break;

    default:
        set_error( STATUS_PIPE_DISCONNECTED );
791
    }
792
    release_object( server );
793
}
794 795 796

DECL_HANDLER(get_named_pipe_info)
{
797
    struct pipe_server *server;
798

799 800
    server = get_pipe_server_obj( current->process, req->handle, 0 );
    if(!server)
801 802
        return;

803 804 805 806
    reply->flags        = server->pipe->pipemode;
    reply->maxinstances = server->pipe->maxinstances;
    reply->insize       = server->pipe->insize;
    reply->outsize      = server->pipe->outsize;
807

808
    release_object(server);
809
}