Avoid problems during changing the Z-order if the window and the
[wine] / server / pipe.c
1 /*
2  * Server-side pipe management
3  *
4  * Copyright (C) 1998 Alexandre Julliard
5  */
6
7 #include "config.h"
8
9 #include <assert.h>
10 #include <fcntl.h>
11 #include <string.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #ifdef HAVE_SYS_ERRNO_H
15 #include <sys/errno.h>
16 #endif
17 #include <sys/stat.h>
18 #include <sys/time.h>
19 #include <sys/types.h>
20 #include <time.h>
21 #include <unistd.h>
22
23 #include "winerror.h"
24 #include "winbase.h"
25
26 #include "handle.h"
27 #include "thread.h"
28 #include "request.h"
29
30 enum side { READ_SIDE, WRITE_SIDE };
31
32 struct pipe
33 {
34     struct object       obj;         /* object header */
35     struct pipe        *other;       /* the pipe other end */
36     enum side           side;        /* which side of the pipe is this */
37 };
38
39 static void pipe_dump( struct object *obj, int verbose );
40 static int pipe_get_poll_events( struct object *obj );
41 static int pipe_get_read_fd( struct object *obj );
42 static int pipe_get_write_fd( struct object *obj );
43 static int pipe_get_info( struct object *obj, struct get_file_info_request *req );
44 static void pipe_destroy( struct object *obj );
45
46 static const struct object_ops pipe_ops =
47 {
48     sizeof(struct pipe),          /* size */
49     pipe_dump,                    /* dump */
50     default_poll_add_queue,       /* add_queue */
51     default_poll_remove_queue,    /* remove_queue */
52     default_poll_signaled,        /* signaled */
53     no_satisfied,                 /* satisfied */
54     pipe_get_poll_events,         /* get_poll_events */
55     default_poll_event,           /* poll_event */
56     pipe_get_read_fd,             /* get_read_fd */
57     pipe_get_write_fd,            /* get_write_fd */
58     no_flush,                     /* flush */
59     pipe_get_info,                /* get_file_info */
60     pipe_destroy                  /* destroy */
61 };
62
63
64 static struct pipe *create_pipe_side( int fd, int side )
65 {
66     struct pipe *pipe;
67
68     if ((pipe = alloc_object( &pipe_ops, fd )))
69     {
70         pipe->other  = NULL;
71         pipe->side   = side;
72     }
73     return pipe;
74 }
75
76 static int create_pipe( struct object *obj[2] )
77 {
78     struct pipe *read_pipe;
79     struct pipe *write_pipe;
80     int fd[2];
81
82     if (pipe( fd ) == -1)
83     {
84         file_set_error();
85         return 0;
86     }
87     if ((read_pipe = create_pipe_side( fd[0], READ_SIDE )))
88     {
89         if ((write_pipe = create_pipe_side( fd[1], WRITE_SIDE )))
90         {
91             write_pipe->other = read_pipe;
92             read_pipe->other  = write_pipe;
93             obj[0] = &read_pipe->obj;
94             obj[1] = &write_pipe->obj;
95             return 1;
96         }
97         release_object( read_pipe );
98     }
99     else close( fd[1] );
100     return 0;
101 }
102
103 static void pipe_dump( struct object *obj, int verbose )
104 {
105     struct pipe *pipe = (struct pipe *)obj;
106     assert( obj->ops == &pipe_ops );
107     fprintf( stderr, "Pipe %s-side fd=%d\n",
108              (pipe->side == READ_SIDE) ? "read" : "write", pipe->obj.fd );
109 }
110
111 static int pipe_get_poll_events( struct object *obj )
112 {
113     struct pipe *pipe = (struct pipe *)obj;
114     assert( obj->ops == &pipe_ops );
115     return (pipe->side == READ_SIDE) ? POLLIN : POLLOUT;
116 }
117
118 static int pipe_get_read_fd( struct object *obj )
119 {
120     struct pipe *pipe = (struct pipe *)obj;
121     assert( obj->ops == &pipe_ops );
122
123     if (!pipe->other)
124     {
125         set_error( ERROR_BROKEN_PIPE );
126         return -1;
127     }
128     if (pipe->side != READ_SIDE)  /* FIXME: should not be necessary */
129     {
130         set_error( ERROR_ACCESS_DENIED );
131         return -1;
132     }
133     return dup( pipe->obj.fd );
134 }
135
136 static int pipe_get_write_fd( struct object *obj )
137 {
138     struct pipe *pipe = (struct pipe *)obj;
139     assert( obj->ops == &pipe_ops );
140
141     if (!pipe->other)
142     {
143         set_error( ERROR_BROKEN_PIPE );
144         return -1;
145     }
146     if (pipe->side != WRITE_SIDE)  /* FIXME: should not be necessary */
147     {
148         set_error( ERROR_ACCESS_DENIED );
149         return -1;
150     }
151     return dup( pipe->obj.fd );
152 }
153
154 static int pipe_get_info( struct object *obj, struct get_file_info_request *req )
155 {
156     req->type        = FILE_TYPE_PIPE;
157     req->attr        = 0;
158     req->access_time = 0;
159     req->write_time  = 0;
160     req->size_high   = 0;
161     req->size_low    = 0;
162     req->links       = 0;
163     req->index_high  = 0;
164     req->index_low   = 0;
165     req->serial      = 0;
166     return 1;
167 }
168
169 static void pipe_destroy( struct object *obj )
170 {
171     struct pipe *pipe = (struct pipe *)obj;
172     assert( obj->ops == &pipe_ops );
173
174     if (pipe->other) pipe->other->other = NULL;
175 }
176
177 /* create an anonymous pipe */
178 DECL_HANDLER(create_pipe)
179 {
180     struct object *obj[2];
181     int hread = -1, hwrite = -1;
182
183     if (create_pipe( obj ))
184     {
185         hread = alloc_handle( current->process, obj[0],
186                               STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_READ,
187                               req->inherit );
188         if (hread != -1)
189         {
190             hwrite = alloc_handle( current->process, obj[1],
191                                    STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|GENERIC_WRITE,
192                                    req->inherit );
193             if (hwrite == -1)
194                 close_handle( current->process, hread );
195         }
196         release_object( obj[0] );
197         release_object( obj[1] );
198     }
199     req->handle_read  = hread;
200     req->handle_write = hwrite;
201 }