mshtml: Added config key to specify Gecko path.
[wine] / server / mailslot.c
1 /*
2  * Server-side mailslot management
3  *
4  * Copyright (C) 1998 Alexandre Julliard
5  * Copyright (C) 2005 Mike McCormack
6  *
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  *
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25 #include "ntstatus.h"
26 #define WIN32_NO_STATUS
27 #include "wine/unicode.h"
28
29 #include <assert.h>
30 #include <fcntl.h>
31 #include <string.h>
32 #include <stdarg.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <sys/time.h>
36 #include <sys/types.h>
37
38 #ifdef HAVE_SYS_IOCTL_H
39 #include <sys/ioctl.h>
40 #endif
41 #ifdef HAVE_SYS_SOCKET_H
42 #include <sys/socket.h>
43 #endif
44 #ifdef HAVE_SYS_FILIO_H
45 #include <sys/filio.h>
46 #endif
47 #include "windef.h"
48 #include "winternl.h"
49
50 #include "file.h"
51 #include "handle.h"
52 #include "thread.h"
53 #include "request.h"
54
55 struct mailslot
56 {
57     struct object       obj;
58     struct fd          *fd;
59     struct fd          *write_fd;
60     unsigned int        max_msgsize;
61     int                 read_timeout;
62     struct list         writers;
63 };
64
65 struct mailslot_device
66 {
67     struct object       obj;         /* object header */
68     struct namespace   *mailslots;   /* mailslot namespace */
69 };
70
71 /* mailslot functions */
72 static void mailslot_dump( struct object*, int );
73 static struct fd *mailslot_get_fd( struct object * );
74 static void mailslot_destroy( struct object * );
75
76 static const struct object_ops mailslot_ops =
77 {
78     sizeof(struct mailslot),   /* size */
79     mailslot_dump,             /* dump */
80     default_fd_add_queue,      /* add_queue */
81     default_fd_remove_queue,   /* remove_queue */
82     default_fd_signaled,       /* signaled */
83     no_satisfied,              /* satisfied */
84     no_signal,                 /* signal */
85     mailslot_get_fd,           /* get_fd */
86     no_lookup_name,            /* lookup_name */
87     no_close_handle,           /* close_handle */
88     mailslot_destroy           /* destroy */
89 };
90
91 static int mailslot_get_info( struct fd * );
92 static void mailslot_queue_async( struct fd *, void*, void*, void*, int, int );
93
94 static const struct fd_ops mailslot_fd_ops =
95 {
96     default_fd_get_poll_events, /* get_poll_events */
97     default_poll_event,         /* poll_event */
98     no_flush,                   /* flush */
99     mailslot_get_info,          /* get_file_info */
100     mailslot_queue_async,       /* queue_async */
101     default_fd_cancel_async     /* cancel_async */
102 };
103
104 struct mail_writer
105 {
106     struct object         obj;
107     struct mailslot      *mailslot;
108     struct list           entry;
109     int                   access;
110     int                   sharing;
111 };
112
113 static void mail_writer_dump( struct object *obj, int verbose );
114 static struct fd *mail_writer_get_fd( struct object *obj );
115 static void mail_writer_destroy( struct object *obj);
116
117 static const struct object_ops mail_writer_ops =
118 {
119     sizeof(struct mail_writer), /* size */
120     mail_writer_dump,           /* dump */
121     no_add_queue,               /* add_queue */
122     NULL,                       /* remove_queue */
123     NULL,                       /* signaled */
124     NULL,                       /* satisfied */
125     no_signal,                  /* signal */
126     mail_writer_get_fd,         /* get_fd */
127     no_lookup_name,             /* lookup_name */
128     no_close_handle,            /* close_handle */
129     mail_writer_destroy         /* destroy */
130 };
131
132 static int mail_writer_get_info( struct fd *fd );
133
134 static const struct fd_ops mail_writer_fd_ops =
135 {
136     NULL,                        /* get_poll_events */
137     NULL,                        /* poll_event */
138     no_flush,                    /* flush */
139     mail_writer_get_info,        /* get_file_info */
140     no_queue_async,              /* queue_async */
141     NULL                         /* cancel_async */
142 };
143
144 static void mailslot_device_dump( struct object *obj, int verbose );
145 static struct object *mailslot_device_lookup_name( struct object *obj, struct unicode_str *name,
146                                                    unsigned int attr );
147 static void mailslot_device_destroy( struct object *obj );
148
149 static const struct object_ops mailslot_device_ops =
150 {
151     sizeof(struct mailslot_device), /* size */
152     mailslot_device_dump,         /* dump */
153     no_add_queue,                 /* add_queue */
154     NULL,                         /* remove_queue */
155     NULL,                         /* signaled */
156     no_satisfied,                 /* satisfied */
157     no_signal,                    /* signal */
158     no_get_fd,                    /* get_fd */
159     mailslot_device_lookup_name,  /* lookup_name */
160     no_close_handle,              /* close_handle */
161     mailslot_device_destroy       /* destroy */
162 };
163
164 static void mailslot_destroy( struct object *obj)
165 {
166     struct mailslot *mailslot = (struct mailslot *) obj;
167
168     assert( mailslot->fd );
169     assert( mailslot->write_fd );
170
171     release_object( mailslot->fd );
172     release_object( mailslot->write_fd );
173 }
174
175 static void mailslot_dump( struct object *obj, int verbose )
176 {
177     struct mailslot *mailslot = (struct mailslot *) obj;
178
179     assert( obj->ops == &mailslot_ops );
180     fprintf( stderr, "Mailslot max_msgsize=%d read_timeout=%d\n",
181              mailslot->max_msgsize, mailslot->read_timeout );
182 }
183
184 static int mailslot_message_count(struct mailslot *mailslot)
185 {
186     struct pollfd pfd;
187
188     /* poll the socket to see if there's any messages */
189     pfd.fd = get_unix_fd( mailslot->fd );
190     pfd.events = POLLIN;
191     pfd.revents = 0;
192     return (poll( &pfd, 1, 0 ) == 1) ? 1 : 0;
193 }
194
195 static int mailslot_next_msg_size( struct mailslot *mailslot )
196 {
197     int size, fd;
198
199     size = 0;
200     fd = get_unix_fd( mailslot->fd );
201     ioctl( fd, FIONREAD, &size );
202     return size;
203 }
204
205 static int mailslot_get_info( struct fd *fd )
206 {
207     struct mailslot *mailslot = get_fd_user( fd );
208     assert( mailslot->obj.ops == &mailslot_ops );
209     return FD_FLAG_TIMEOUT | FD_FLAG_AVAILABLE;
210 }
211
212 static struct fd *mailslot_get_fd( struct object *obj )
213 {
214     struct mailslot *mailslot = (struct mailslot *) obj;
215
216     return (struct fd *)grab_object( mailslot->fd );
217 }
218
219 static void mailslot_queue_async( struct fd *fd, void *apc, void *user,
220                                   void *iosb, int type, int count )
221 {
222     struct mailslot *mailslot = get_fd_user( fd );
223     int *timeout = NULL;
224
225     assert(mailslot->obj.ops == &mailslot_ops);
226
227     if (type != ASYNC_TYPE_READ)
228     {
229         set_error(STATUS_INVALID_PARAMETER);
230         return;
231     }
232
233     if (list_empty( &mailslot->writers ) ||
234         !mailslot_message_count( mailslot ))
235     {
236         set_error(STATUS_IO_TIMEOUT);
237         return;
238     }
239
240     if (mailslot->read_timeout != -1) timeout = &mailslot->read_timeout;
241
242     fd_queue_async_timeout( fd, apc, user, iosb, type, count, timeout );
243 }
244
245 static void mailslot_device_dump( struct object *obj, int verbose )
246 {
247     assert( obj->ops == &mailslot_device_ops );
248     fprintf( stderr, "Mail slot device\n" );
249 }
250
251 static struct object *mailslot_device_lookup_name( struct object *obj, struct unicode_str *name,
252                                                    unsigned int attr )
253 {
254     struct mailslot_device *device = (struct mailslot_device*)obj;
255     struct object *found;
256
257     assert( obj->ops == &mailslot_device_ops );
258
259     if ((found = find_object( device->mailslots, name, attr | OBJ_CASE_INSENSITIVE )))
260         name->len = 0;
261
262     return found;
263 }
264
265 static void mailslot_device_destroy( struct object *obj )
266 {
267     struct mailslot_device *device = (struct mailslot_device*)obj;
268     assert( obj->ops == &mailslot_device_ops );
269     free( device->mailslots );
270 }
271
272 struct mailslot_device *create_mailslot_device( struct directory *root, const struct unicode_str *name )
273 {
274     struct mailslot_device *dev;
275
276     if ((dev = create_named_object_dir( root, name, 0, &mailslot_device_ops )) &&
277         get_error() != STATUS_OBJECT_NAME_EXISTS)
278     {
279         if (!(dev->mailslots = create_namespace( 7 )))
280         {
281             release_object( dev );
282             dev = NULL;
283         }
284     }
285     return dev;
286 }
287
288 static struct mailslot *create_mailslot( struct directory *root,
289                                          const struct unicode_str *name, unsigned int attr,
290                                          int max_msgsize, int read_timeout )
291 {
292     struct object *obj;
293     struct unicode_str new_name;
294     struct mailslot_device *dev;
295     struct mailslot *mailslot;
296     int fds[2];
297
298     if (!name || !name->len) return alloc_object( &mailslot_ops );
299
300     if (!(obj = find_object_dir( root, name, attr, &new_name ))) return NULL;
301
302     if (!new_name.len)
303     {
304         if (attr & OBJ_OPENIF && obj->ops == &mailslot_ops)
305             /* it already exists - there can only be one mailslot to read from */
306             set_error( STATUS_OBJECT_NAME_EXISTS );
307         else if (attr & OBJ_OPENIF)
308             set_error( STATUS_OBJECT_TYPE_MISMATCH );
309         else
310             set_error( STATUS_OBJECT_NAME_COLLISION );
311         release_object( obj );
312         return NULL;
313     }
314
315     if (obj->ops != &mailslot_device_ops)
316     {
317         set_error( STATUS_OBJECT_TYPE_MISMATCH );
318         release_object( obj );
319         return NULL;
320     }
321
322     dev = (struct mailslot_device *)obj;
323     mailslot = create_object( dev->mailslots, &mailslot_ops, &new_name, NULL );
324     release_object( dev );
325
326     if (!mailslot) return NULL;
327
328     mailslot->fd = NULL;
329     mailslot->write_fd = NULL;
330     mailslot->max_msgsize = max_msgsize;
331     mailslot->read_timeout = read_timeout;
332     list_init( &mailslot->writers );
333
334     if (!socketpair( PF_UNIX, SOCK_DGRAM, 0, fds ))
335     {
336         fcntl( fds[0], F_SETFL, O_NONBLOCK );
337         fcntl( fds[1], F_SETFL, O_NONBLOCK );
338         mailslot->fd = create_anonymous_fd( &mailslot_fd_ops,
339                                 fds[1], &mailslot->obj );
340         mailslot->write_fd = create_anonymous_fd( &mail_writer_fd_ops,
341                                 fds[0], &mailslot->obj );
342         if (mailslot->fd && mailslot->write_fd) return mailslot;
343     }
344     else file_set_error();
345
346     release_object( mailslot );
347     return NULL;
348 }
349
350 static void mail_writer_dump( struct object *obj, int verbose )
351 {
352     fprintf( stderr, "Mailslot writer\n" );
353 }
354
355 static void mail_writer_destroy( struct object *obj)
356 {
357     struct mail_writer *writer = (struct mail_writer *) obj;
358
359     list_remove( &writer->entry );
360     release_object( writer->mailslot );
361 }
362
363 static int mail_writer_get_info( struct fd *fd )
364 {
365     return 0;
366 }
367
368 static struct fd *mail_writer_get_fd( struct object *obj )
369 {
370     struct mail_writer *writer = (struct mail_writer *) obj;
371
372     return (struct fd *)grab_object( writer->mailslot->write_fd );
373 }
374
375 /*
376  * Readers and writers cannot be mixed.
377  * If there's more than one writer, all writers must open with FILE_SHARE_WRITE
378  */
379 static struct mail_writer *create_mail_writer( struct mailslot *mailslot, unsigned int access,
380                                                unsigned int sharing )
381 {
382     struct mail_writer *writer;
383
384     if (!list_empty( &mailslot->writers ))
385     {
386         writer = LIST_ENTRY( list_head(&mailslot->writers), struct mail_writer, entry );
387
388         if (((access & GENERIC_WRITE) || (writer->access & GENERIC_WRITE)) &&
389            !((sharing & FILE_SHARE_WRITE) && (writer->sharing & FILE_SHARE_WRITE)))
390         {
391             set_error( STATUS_SHARING_VIOLATION );
392             return NULL;
393         }
394     }
395
396     writer = alloc_object( &mail_writer_ops );
397     if (!writer)
398         return NULL;
399
400     grab_object( mailslot );
401     writer->mailslot = mailslot;
402     writer->access = access;
403     writer->sharing = sharing;
404
405     list_add_head( &mailslot->writers, &writer->entry );
406
407     return writer;
408 }
409
410 static struct mailslot *get_mailslot_obj( struct process *process, obj_handle_t handle,
411                                           unsigned int access )
412 {
413     return (struct mailslot *)get_handle_obj( process, handle, access, &mailslot_ops );
414 }
415
416
417 /* create a mailslot */
418 DECL_HANDLER(create_mailslot)
419 {
420     struct mailslot *mailslot;
421     struct unicode_str name;
422     struct directory *root = NULL;
423
424     reply->handle = 0;
425     get_req_unicode_str( &name );
426     if (req->rootdir && !(root = get_directory_obj( current->process, req->rootdir, 0 )))
427         return;
428
429     if ((mailslot = create_mailslot( root, &name, req->attributes, req->max_msgsize,
430                                      req->read_timeout )))
431     {
432         reply->handle = alloc_handle( current->process, mailslot,
433                                       req->access, req->attributes & OBJ_INHERIT );
434         release_object( mailslot );
435     }
436
437     if (root) release_object( root );
438 }
439
440
441 /* open an existing mailslot */
442 DECL_HANDLER(open_mailslot)
443 {
444     struct mailslot *mailslot;
445     struct unicode_str name;
446     struct directory *root = NULL;
447
448     reply->handle = 0;
449     get_req_unicode_str( &name );
450
451     if (!(req->sharing & FILE_SHARE_READ))
452     {
453         set_error( STATUS_SHARING_VIOLATION );
454         return;
455     }
456
457     if (req->rootdir && !(root = get_directory_obj( current->process, req->rootdir, 0 )))
458         return;
459     mailslot = open_object_dir( root, &name, req->attributes, &mailslot_ops );
460     if (root) release_object( root );
461
462     if (mailslot)
463     {
464         struct mail_writer *writer;
465
466         writer = create_mail_writer( mailslot, req->access, req->sharing );
467         if (writer)
468         {
469             reply->handle = alloc_handle( current->process, writer,
470                                           req->access, req->attributes & OBJ_INHERIT );
471             release_object( writer );
472         }
473         release_object( mailslot );
474     }
475     else
476         set_error( STATUS_NO_SUCH_FILE );
477 }
478
479
480 /* set mailslot information */
481 DECL_HANDLER(set_mailslot_info)
482 {
483     struct mailslot *mailslot = get_mailslot_obj( current->process, req->handle, 0 );
484
485     if (mailslot)
486     {
487         if (req->flags & MAILSLOT_SET_READ_TIMEOUT)
488             mailslot->read_timeout = req->read_timeout;
489         reply->max_msgsize = mailslot->max_msgsize;
490         reply->read_timeout = mailslot->read_timeout;
491         reply->msg_count = mailslot_message_count(mailslot);
492
493         /* get the size of the next message */
494         if (reply->msg_count)
495             reply->next_msgsize = mailslot_next_msg_size(mailslot);
496         else
497             reply->next_msgsize = MAILSLOT_NO_MESSAGE;
498
499         release_object( mailslot );
500     }
501 }