blob: e223b8373e1c897d3b79c876b2876ac7da8caef9 [file] [log] [blame]
Mike McCormack2ab6a772005-03-30 19:02:15 +00001/*
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
Jonathan Ernst360a3f92006-05-18 14:49:52 +020019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Mike McCormack2ab6a772005-03-30 19:02:15 +000020 *
21 */
22
23#include "config.h"
24#include "wine/port.h"
Ge van Geldorp1a1583a2005-11-28 17:32:54 +010025#include "ntstatus.h"
26#define WIN32_NO_STATUS
Mike McCormack2ab6a772005-03-30 19:02:15 +000027#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
Robert Lunnon43e41392005-05-07 12:14:18 +000044#ifdef HAVE_SYS_FILIO_H
45#include <sys/filio.h>
46#endif
Mike McCormack2ab6a772005-03-30 19:02:15 +000047#include "windef.h"
Vitaliy Margolena9960002005-10-27 18:30:37 +000048#include "winternl.h"
Mike McCormack2ab6a772005-03-30 19:02:15 +000049
50#include "file.h"
51#include "handle.h"
52#include "thread.h"
53#include "request.h"
54
55struct mailslot
56{
57 struct object obj;
58 struct fd *fd;
Alexandre Julliard72ff2bf2007-04-12 20:19:28 +020059 int write_fd;
Mike McCormack2ab6a772005-03-30 19:02:15 +000060 unsigned int max_msgsize;
Alexandre Julliardaaf477f2007-04-17 20:08:59 +020061 timeout_t read_timeout;
Mike McCormack2ab6a772005-03-30 19:02:15 +000062 struct list writers;
Mike McCormack2ab6a772005-03-30 19:02:15 +000063};
64
65/* mailslot functions */
66static void mailslot_dump( struct object*, int );
67static struct fd *mailslot_get_fd( struct object * );
Alexandre Julliarda510a7e2005-12-12 16:46:17 +010068static unsigned int mailslot_map_access( struct object *obj, unsigned int access );
Alexandre Julliard806bb492007-03-22 16:36:54 +010069static struct object *mailslot_open_file( struct object *obj, unsigned int access,
70 unsigned int sharing, unsigned int options );
Mike McCormack2ab6a772005-03-30 19:02:15 +000071static void mailslot_destroy( struct object * );
72
73static const struct object_ops mailslot_ops =
74{
75 sizeof(struct mailslot), /* size */
76 mailslot_dump, /* dump */
Alexandre Julliard8382eb02007-12-05 18:16:42 +010077 no_get_type, /* get_type */
Alexandre Julliardba896e72007-04-04 19:39:29 +020078 add_queue, /* add_queue */
79 remove_queue, /* remove_queue */
Mike McCormack2ab6a772005-03-30 19:02:15 +000080 default_fd_signaled, /* signaled */
81 no_satisfied, /* satisfied */
Mike McCormackf92fff62005-04-24 17:35:52 +000082 no_signal, /* signal */
Mike McCormack2ab6a772005-03-30 19:02:15 +000083 mailslot_get_fd, /* get_fd */
Alexandre Julliarda510a7e2005-12-12 16:46:17 +010084 mailslot_map_access, /* map_access */
Rob Shearmanc1707d82007-10-03 13:10:37 +010085 default_get_sd, /* get_sd */
86 default_set_sd, /* set_sd */
Vitaliy Margolenbaffcb92005-11-22 14:55:42 +000087 no_lookup_name, /* lookup_name */
Alexandre Julliard806bb492007-03-22 16:36:54 +010088 mailslot_open_file, /* open_file */
Alexandre Julliard715d78e2006-11-02 20:52:22 +010089 fd_close_handle, /* close_handle */
Mike McCormack2ab6a772005-03-30 19:02:15 +000090 mailslot_destroy /* destroy */
91};
92
Alexandre Julliard7a9363a2007-04-10 22:26:23 +020093static enum server_fd_type mailslot_get_fd_type( struct fd *fd );
Alexandre Julliard111610c2007-03-20 20:21:12 +010094static void mailslot_queue_async( struct fd *fd, const async_data_t *data, int type, int count );
Mike McCormack2ab6a772005-03-30 19:02:15 +000095
96static const struct fd_ops mailslot_fd_ops =
97{
Robert Shearman37773dd2005-07-14 12:18:05 +000098 default_fd_get_poll_events, /* get_poll_events */
99 default_poll_event, /* poll_event */
100 no_flush, /* flush */
Alexandre Julliard7a9363a2007-04-10 22:26:23 +0200101 mailslot_get_fd_type, /* get_fd_type */
Alexandre Julliard63571432007-04-16 14:45:03 +0200102 default_fd_ioctl, /* ioctl */
Robert Shearman37773dd2005-07-14 12:18:05 +0000103 mailslot_queue_async, /* queue_async */
Alexandre Julliard72bff2e2007-04-10 17:07:27 +0200104 default_fd_reselect_async, /* reselect_async */
Robert Shearman37773dd2005-07-14 12:18:05 +0000105 default_fd_cancel_async /* cancel_async */
Mike McCormack2ab6a772005-03-30 19:02:15 +0000106};
107
Alexandre Julliarda510a7e2005-12-12 16:46:17 +0100108
Mike McCormack2ab6a772005-03-30 19:02:15 +0000109struct mail_writer
110{
111 struct object obj;
Alexandre Julliard72ff2bf2007-04-12 20:19:28 +0200112 struct fd *fd;
Mike McCormack2ab6a772005-03-30 19:02:15 +0000113 struct mailslot *mailslot;
114 struct list entry;
Alexandre Julliarda510a7e2005-12-12 16:46:17 +0100115 unsigned int access;
116 unsigned int sharing;
Mike McCormack2ab6a772005-03-30 19:02:15 +0000117};
118
119static void mail_writer_dump( struct object *obj, int verbose );
120static struct fd *mail_writer_get_fd( struct object *obj );
Alexandre Julliarda510a7e2005-12-12 16:46:17 +0100121static unsigned int mail_writer_map_access( struct object *obj, unsigned int access );
Mike McCormack2ab6a772005-03-30 19:02:15 +0000122static void mail_writer_destroy( struct object *obj);
123
124static const struct object_ops mail_writer_ops =
125{
126 sizeof(struct mail_writer), /* size */
127 mail_writer_dump, /* dump */
Alexandre Julliard8382eb02007-12-05 18:16:42 +0100128 no_get_type, /* get_type */
Mike McCormack2ab6a772005-03-30 19:02:15 +0000129 no_add_queue, /* add_queue */
130 NULL, /* remove_queue */
131 NULL, /* signaled */
132 NULL, /* satisfied */
Mike McCormackf92fff62005-04-24 17:35:52 +0000133 no_signal, /* signal */
Mike McCormack2ab6a772005-03-30 19:02:15 +0000134 mail_writer_get_fd, /* get_fd */
Alexandre Julliarda510a7e2005-12-12 16:46:17 +0100135 mail_writer_map_access, /* map_access */
Rob Shearmanc1707d82007-10-03 13:10:37 +0100136 default_get_sd, /* get_sd */
137 default_set_sd, /* set_sd */
Vitaliy Margolenbaffcb92005-11-22 14:55:42 +0000138 no_lookup_name, /* lookup_name */
Alexandre Julliard7e71c1d2007-03-22 11:44:29 +0100139 no_open_file, /* open_file */
Alexandre Julliard715d78e2006-11-02 20:52:22 +0100140 fd_close_handle, /* close_handle */
Mike McCormack2ab6a772005-03-30 19:02:15 +0000141 mail_writer_destroy /* destroy */
142};
143
Alexandre Julliard7a9363a2007-04-10 22:26:23 +0200144static enum server_fd_type mail_writer_get_fd_type( struct fd *fd );
Mike McCormack2ab6a772005-03-30 19:02:15 +0000145
146static const struct fd_ops mail_writer_fd_ops =
147{
Alexandre Julliard72ff2bf2007-04-12 20:19:28 +0200148 default_fd_get_poll_events, /* get_poll_events */
149 default_poll_event, /* poll_event */
Mike McCormack2ab6a772005-03-30 19:02:15 +0000150 no_flush, /* flush */
Alexandre Julliard7a9363a2007-04-10 22:26:23 +0200151 mail_writer_get_fd_type, /* get_fd_type */
Alexandre Julliard63571432007-04-16 14:45:03 +0200152 default_fd_ioctl, /* ioctl */
Alexandre Julliard72ff2bf2007-04-12 20:19:28 +0200153 default_fd_queue_async, /* queue_async */
154 default_fd_reselect_async, /* reselect_async */
155 default_fd_cancel_async /* cancel_async */
Mike McCormack2ab6a772005-03-30 19:02:15 +0000156};
157
Alexandre Julliarda510a7e2005-12-12 16:46:17 +0100158
159struct mailslot_device
160{
161 struct object obj; /* object header */
162 struct fd *fd; /* pseudo-fd for ioctls */
163 struct namespace *mailslots; /* mailslot namespace */
164};
165
Vitaliy Margolencf21d4d2005-12-05 13:30:26 +0100166static void mailslot_device_dump( struct object *obj, int verbose );
Alexandre Julliard8382eb02007-12-05 18:16:42 +0100167static struct object_type *mailslot_device_get_type( struct object *obj );
Alexandre Julliardb0aa29e2005-12-12 14:39:27 +0100168static struct fd *mailslot_device_get_fd( struct object *obj );
Vitaliy Margolencf21d4d2005-12-05 13:30:26 +0100169static struct object *mailslot_device_lookup_name( struct object *obj, struct unicode_str *name,
170 unsigned int attr );
Alexandre Julliard94655c82007-03-22 11:52:40 +0100171static struct object *mailslot_device_open_file( struct object *obj, unsigned int access,
172 unsigned int sharing, unsigned int options );
Vitaliy Margolencf21d4d2005-12-05 13:30:26 +0100173static void mailslot_device_destroy( struct object *obj );
Alexandre Julliard7a9363a2007-04-10 22:26:23 +0200174static enum server_fd_type mailslot_device_get_fd_type( struct fd *fd );
Vitaliy Margolencf21d4d2005-12-05 13:30:26 +0100175
176static const struct object_ops mailslot_device_ops =
177{
178 sizeof(struct mailslot_device), /* size */
Alexandre Julliardb0aa29e2005-12-12 14:39:27 +0100179 mailslot_device_dump, /* dump */
Alexandre Julliard8382eb02007-12-05 18:16:42 +0100180 mailslot_device_get_type, /* get_type */
Alexandre Julliardb0aa29e2005-12-12 14:39:27 +0100181 no_add_queue, /* add_queue */
182 NULL, /* remove_queue */
183 NULL, /* signaled */
184 no_satisfied, /* satisfied */
185 no_signal, /* signal */
186 mailslot_device_get_fd, /* get_fd */
Alexandre Julliard28beba32005-12-12 14:57:40 +0100187 no_map_access, /* map_access */
Rob Shearmanc1707d82007-10-03 13:10:37 +0100188 default_get_sd, /* get_sd */
189 default_set_sd, /* set_sd */
Alexandre Julliardb0aa29e2005-12-12 14:39:27 +0100190 mailslot_device_lookup_name, /* lookup_name */
Alexandre Julliard94655c82007-03-22 11:52:40 +0100191 mailslot_device_open_file, /* open_file */
Alexandre Julliard715d78e2006-11-02 20:52:22 +0100192 fd_close_handle, /* close_handle */
Alexandre Julliardb0aa29e2005-12-12 14:39:27 +0100193 mailslot_device_destroy /* destroy */
194};
195
196static const struct fd_ops mailslot_device_fd_ops =
197{
Alexandre Julliard1acb9302005-12-13 12:00:11 +0100198 default_fd_get_poll_events, /* get_poll_events */
199 default_poll_event, /* poll_event */
200 no_flush, /* flush */
Alexandre Julliard7a9363a2007-04-10 22:26:23 +0200201 mailslot_device_get_fd_type, /* get_fd_type */
Alexandre Julliard63571432007-04-16 14:45:03 +0200202 default_fd_ioctl, /* ioctl */
Alexandre Julliard1acb9302005-12-13 12:00:11 +0100203 default_fd_queue_async, /* queue_async */
Alexandre Julliard72bff2e2007-04-10 17:07:27 +0200204 default_fd_reselect_async, /* reselect_async */
Alexandre Julliard1acb9302005-12-13 12:00:11 +0100205 default_fd_cancel_async /* cancel_async */
Vitaliy Margolencf21d4d2005-12-05 13:30:26 +0100206};
207
Mike McCormack2ab6a772005-03-30 19:02:15 +0000208static void mailslot_destroy( struct object *obj)
209{
210 struct mailslot *mailslot = (struct mailslot *) obj;
211
212 assert( mailslot->fd );
Mike McCormack2ab6a772005-03-30 19:02:15 +0000213
Alexandre Julliard72ff2bf2007-04-12 20:19:28 +0200214 if (mailslot->write_fd != -1)
215 {
216 shutdown( mailslot->write_fd, SHUT_RDWR );
217 close( mailslot->write_fd );
218 }
Mike McCormack2ab6a772005-03-30 19:02:15 +0000219 release_object( mailslot->fd );
Mike McCormack2ab6a772005-03-30 19:02:15 +0000220}
221
222static void mailslot_dump( struct object *obj, int verbose )
223{
224 struct mailslot *mailslot = (struct mailslot *) obj;
225
226 assert( obj->ops == &mailslot_ops );
Alexandre Julliardaaf477f2007-04-17 20:08:59 +0200227 fprintf( stderr, "Mailslot max_msgsize=%d read_timeout=%s\n",
228 mailslot->max_msgsize, get_timeout_str(mailslot->read_timeout) );
Mike McCormack2ab6a772005-03-30 19:02:15 +0000229}
230
Alexandre Julliard7a9363a2007-04-10 22:26:23 +0200231static enum server_fd_type mailslot_get_fd_type( struct fd *fd )
Mike McCormack2ab6a772005-03-30 19:02:15 +0000232{
Alexandre Julliard89304272006-11-20 14:14:04 +0100233 return FD_TYPE_MAILSLOT;
Mike McCormack2ab6a772005-03-30 19:02:15 +0000234}
235
236static struct fd *mailslot_get_fd( struct object *obj )
237{
238 struct mailslot *mailslot = (struct mailslot *) obj;
239
240 return (struct fd *)grab_object( mailslot->fd );
241}
242
Alexandre Julliarda510a7e2005-12-12 16:46:17 +0100243static unsigned int mailslot_map_access( struct object *obj, unsigned int access )
244{
Alexandre Julliard02ed7042007-04-02 20:24:55 +0200245 /* mailslots can only be read */
Alexandre Julliarda510a7e2005-12-12 16:46:17 +0100246 if (access & GENERIC_READ) access |= FILE_GENERIC_READ;
Alexandre Julliard02ed7042007-04-02 20:24:55 +0200247 if (access & GENERIC_ALL) access |= FILE_GENERIC_READ;
Alexandre Julliarda510a7e2005-12-12 16:46:17 +0100248 return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
249}
250
Alexandre Julliard806bb492007-03-22 16:36:54 +0100251static struct object *mailslot_open_file( struct object *obj, unsigned int access,
252 unsigned int sharing, unsigned int options )
253{
254 struct mailslot *mailslot = (struct mailslot *)obj;
255 struct mail_writer *writer;
Alexandre Julliard72ff2bf2007-04-12 20:19:28 +0200256 int unix_fd;
Alexandre Julliard806bb492007-03-22 16:36:54 +0100257
258 if (!(sharing & FILE_SHARE_READ))
259 {
260 set_error( STATUS_SHARING_VIOLATION );
261 return NULL;
262 }
263
264 if (!list_empty( &mailslot->writers ))
265 {
266 /* Readers and writers cannot be mixed.
267 * If there's more than one writer, all writers must open with FILE_SHARE_WRITE
268 */
269 writer = LIST_ENTRY( list_head(&mailslot->writers), struct mail_writer, entry );
270
271 if (((access & (GENERIC_WRITE|FILE_WRITE_DATA)) || (writer->access & FILE_WRITE_DATA)) &&
272 !((sharing & FILE_SHARE_WRITE) && (writer->sharing & FILE_SHARE_WRITE)))
273 {
274 set_error( STATUS_SHARING_VIOLATION );
275 return NULL;
276 }
277 }
278
Alexandre Julliard72ff2bf2007-04-12 20:19:28 +0200279 if ((unix_fd = dup( mailslot->write_fd )) == -1)
280 {
281 file_set_error();
282 return NULL;
283 }
284 if (!(writer = alloc_object( &mail_writer_ops )))
285 {
286 close( unix_fd );
287 return NULL;
288 }
Alexandre Julliard806bb492007-03-22 16:36:54 +0100289 grab_object( mailslot );
290 writer->mailslot = mailslot;
291 writer->access = mail_writer_map_access( &writer->obj, access );
292 writer->sharing = sharing;
Alexandre Julliard806bb492007-03-22 16:36:54 +0100293 list_add_head( &mailslot->writers, &writer->entry );
Alexandre Julliard72ff2bf2007-04-12 20:19:28 +0200294
295 if (!(writer->fd = create_anonymous_fd( &mail_writer_fd_ops, unix_fd, &writer->obj, options )))
296 {
297 release_object( writer );
298 return NULL;
299 }
Alexandre Julliard806bb492007-03-22 16:36:54 +0100300 return &writer->obj;
301}
302
Alexandre Julliard111610c2007-03-20 20:21:12 +0100303static void mailslot_queue_async( struct fd *fd, const async_data_t *data, int type, int count )
Mike McCormack2ab6a772005-03-30 19:02:15 +0000304{
305 struct mailslot *mailslot = get_fd_user( fd );
Alexandre Julliard0aae1ca2007-04-02 20:41:59 +0200306 struct async *async;
Mike McCormack2ab6a772005-03-30 19:02:15 +0000307
308 assert(mailslot->obj.ops == &mailslot_ops);
309
Alexandre Julliard0aae1ca2007-04-02 20:41:59 +0200310 if ((async = fd_queue_async( fd, data, type, count )))
Alexandre Julliard40723f72006-07-26 11:47:42 +0200311 {
Alexandre Julliardaaf477f2007-04-17 20:08:59 +0200312 async_set_timeout( async, mailslot->read_timeout ? mailslot->read_timeout : -1,
313 STATUS_IO_TIMEOUT );
Alexandre Julliard0aae1ca2007-04-02 20:41:59 +0200314 release_object( async );
315 set_error( STATUS_PENDING );
Alexandre Julliard40723f72006-07-26 11:47:42 +0200316 }
Mike McCormack2ab6a772005-03-30 19:02:15 +0000317}
318
Vitaliy Margolencf21d4d2005-12-05 13:30:26 +0100319static void mailslot_device_dump( struct object *obj, int verbose )
320{
321 assert( obj->ops == &mailslot_device_ops );
322 fprintf( stderr, "Mail slot device\n" );
323}
324
Alexandre Julliard8382eb02007-12-05 18:16:42 +0100325static struct object_type *mailslot_device_get_type( struct object *obj )
326{
327 static const WCHAR name[] = {'D','e','v','i','c','e'};
328 static const struct unicode_str str = { name, sizeof(name) };
329 return get_object_type( &str );
330}
331
Alexandre Julliardb0aa29e2005-12-12 14:39:27 +0100332static struct fd *mailslot_device_get_fd( struct object *obj )
333{
334 struct mailslot_device *device = (struct mailslot_device *)obj;
Alexandre Julliard5bcd0882005-12-13 11:22:28 +0100335 return (struct fd *)grab_object( device->fd );
Alexandre Julliardb0aa29e2005-12-12 14:39:27 +0100336}
337
Vitaliy Margolencf21d4d2005-12-05 13:30:26 +0100338static struct object *mailslot_device_lookup_name( struct object *obj, struct unicode_str *name,
339 unsigned int attr )
340{
341 struct mailslot_device *device = (struct mailslot_device*)obj;
342 struct object *found;
343
344 assert( obj->ops == &mailslot_device_ops );
345
346 if ((found = find_object( device->mailslots, name, attr | OBJ_CASE_INSENSITIVE )))
347 name->len = 0;
348
349 return found;
350}
351
Alexandre Julliard94655c82007-03-22 11:52:40 +0100352static struct object *mailslot_device_open_file( struct object *obj, unsigned int access,
353 unsigned int sharing, unsigned int options )
354{
355 return grab_object( obj );
356}
357
Vitaliy Margolencf21d4d2005-12-05 13:30:26 +0100358static void mailslot_device_destroy( struct object *obj )
359{
360 struct mailslot_device *device = (struct mailslot_device*)obj;
361 assert( obj->ops == &mailslot_device_ops );
Alexandre Julliardb0aa29e2005-12-12 14:39:27 +0100362 if (device->fd) release_object( device->fd );
Michael Stefaniuc5ceccec2006-10-09 23:34:36 +0200363 free( device->mailslots );
Vitaliy Margolencf21d4d2005-12-05 13:30:26 +0100364}
365
Alexandre Julliard7a9363a2007-04-10 22:26:23 +0200366static enum server_fd_type mailslot_device_get_fd_type( struct fd *fd )
Alexandre Julliard1acb9302005-12-13 12:00:11 +0100367{
Alexandre Julliard89304272006-11-20 14:14:04 +0100368 return FD_TYPE_DEVICE;
Alexandre Julliard1acb9302005-12-13 12:00:11 +0100369}
370
Alexandre Julliardb00fb172006-03-22 20:32:04 +0100371void create_mailslot_device( struct directory *root, const struct unicode_str *name )
Vitaliy Margolencf21d4d2005-12-05 13:30:26 +0100372{
Vitaliy Margolencf21d4d2005-12-05 13:30:26 +0100373 struct mailslot_device *dev;
374
Alexandre Julliardd13095b2005-12-05 14:52:02 +0100375 if ((dev = create_named_object_dir( root, name, 0, &mailslot_device_ops )) &&
Vitaliy Margolencf21d4d2005-12-05 13:30:26 +0100376 get_error() != STATUS_OBJECT_NAME_EXISTS)
377 {
Alexandre Julliardb0aa29e2005-12-12 14:39:27 +0100378 dev->mailslots = NULL;
Alexandre Julliard017480d2007-05-03 16:07:30 +0200379 if (!(dev->fd = alloc_pseudo_fd( &mailslot_device_fd_ops, &dev->obj, 0 )) ||
Alexandre Julliardb0aa29e2005-12-12 14:39:27 +0100380 !(dev->mailslots = create_namespace( 7 )))
Vitaliy Margolencf21d4d2005-12-05 13:30:26 +0100381 {
382 release_object( dev );
383 dev = NULL;
384 }
385 }
Alexandre Julliardb00fb172006-03-22 20:32:04 +0100386 if (dev) make_object_static( &dev->obj );
Vitaliy Margolencf21d4d2005-12-05 13:30:26 +0100387}
388
389static struct mailslot *create_mailslot( struct directory *root,
390 const struct unicode_str *name, unsigned int attr,
Alexandre Julliardaaf477f2007-04-17 20:08:59 +0200391 int max_msgsize, timeout_t read_timeout )
Mike McCormack2ab6a772005-03-30 19:02:15 +0000392{
Vitaliy Margolencf21d4d2005-12-05 13:30:26 +0100393 struct object *obj;
394 struct unicode_str new_name;
395 struct mailslot_device *dev;
Mike McCormack2ab6a772005-03-30 19:02:15 +0000396 struct mailslot *mailslot;
397 int fds[2];
Mike McCormack2ab6a772005-03-30 19:02:15 +0000398
Vitaliy Margolencf21d4d2005-12-05 13:30:26 +0100399 if (!name || !name->len) return alloc_object( &mailslot_ops );
400
Alexandre Julliard928d28f2007-03-22 14:41:37 +0100401 if (!(obj = find_object_dir( root, name, attr, &new_name )))
402 {
403 set_error( STATUS_OBJECT_NAME_INVALID );
404 return NULL;
405 }
Vitaliy Margolencf21d4d2005-12-05 13:30:26 +0100406
407 if (!new_name.len)
Mike McCormack2ab6a772005-03-30 19:02:15 +0000408 {
Vitaliy Margolencf21d4d2005-12-05 13:30:26 +0100409 if (attr & OBJ_OPENIF && obj->ops == &mailslot_ops)
410 /* it already exists - there can only be one mailslot to read from */
411 set_error( STATUS_OBJECT_NAME_EXISTS );
412 else if (attr & OBJ_OPENIF)
413 set_error( STATUS_OBJECT_TYPE_MISMATCH );
414 else
415 set_error( STATUS_OBJECT_NAME_COLLISION );
416 release_object( obj );
Mike McCormack2ab6a772005-03-30 19:02:15 +0000417 return NULL;
418 }
419
Vitaliy Margolencf21d4d2005-12-05 13:30:26 +0100420 if (obj->ops != &mailslot_device_ops)
Mike McCormack2ab6a772005-03-30 19:02:15 +0000421 {
Alexandre Julliard928d28f2007-03-22 14:41:37 +0100422 set_error( STATUS_OBJECT_NAME_INVALID );
Vitaliy Margolencf21d4d2005-12-05 13:30:26 +0100423 release_object( obj );
Mike McCormack2ab6a772005-03-30 19:02:15 +0000424 return NULL;
425 }
426
Vitaliy Margolencf21d4d2005-12-05 13:30:26 +0100427 dev = (struct mailslot_device *)obj;
428 mailslot = create_object( dev->mailslots, &mailslot_ops, &new_name, NULL );
429 release_object( dev );
430
431 if (!mailslot) return NULL;
432
Mike McCormack2ab6a772005-03-30 19:02:15 +0000433 mailslot->fd = NULL;
Alexandre Julliard72ff2bf2007-04-12 20:19:28 +0200434 mailslot->write_fd = -1;
Mike McCormack2ab6a772005-03-30 19:02:15 +0000435 mailslot->max_msgsize = max_msgsize;
436 mailslot->read_timeout = read_timeout;
437 list_init( &mailslot->writers );
Mike McCormack2ab6a772005-03-30 19:02:15 +0000438
Robert Shearman37957092005-06-10 19:54:46 +0000439 if (!socketpair( PF_UNIX, SOCK_DGRAM, 0, fds ))
Mike McCormack2ab6a772005-03-30 19:02:15 +0000440 {
441 fcntl( fds[0], F_SETFL, O_NONBLOCK );
442 fcntl( fds[1], F_SETFL, O_NONBLOCK );
Alexandre Julliardbc426ab2007-04-10 21:30:37 +0200443 shutdown( fds[0], SHUT_RD );
Alexandre Julliard72ff2bf2007-04-12 20:19:28 +0200444 mailslot->write_fd = fds[0];
Alexandre Julliardf85437c2007-04-10 22:25:07 +0200445 mailslot->fd = create_anonymous_fd( &mailslot_fd_ops, fds[1], &mailslot->obj,
446 FILE_SYNCHRONOUS_IO_NONALERT );
Alexandre Julliard72ff2bf2007-04-12 20:19:28 +0200447 if (mailslot->fd) return mailslot;
Mike McCormack2ab6a772005-03-30 19:02:15 +0000448 }
449 else file_set_error();
450
451 release_object( mailslot );
452 return NULL;
453}
454
Mike McCormack2ab6a772005-03-30 19:02:15 +0000455static void mail_writer_dump( struct object *obj, int verbose )
456{
457 fprintf( stderr, "Mailslot writer\n" );
458}
459
460static void mail_writer_destroy( struct object *obj)
461{
462 struct mail_writer *writer = (struct mail_writer *) obj;
463
Alexandre Julliard72ff2bf2007-04-12 20:19:28 +0200464 if (writer->fd) release_object( writer->fd );
Mike McCormack2ab6a772005-03-30 19:02:15 +0000465 list_remove( &writer->entry );
466 release_object( writer->mailslot );
467}
468
Alexandre Julliard7a9363a2007-04-10 22:26:23 +0200469static enum server_fd_type mail_writer_get_fd_type( struct fd *fd )
Mike McCormack2ab6a772005-03-30 19:02:15 +0000470{
Alexandre Julliard89304272006-11-20 14:14:04 +0100471 return FD_TYPE_MAILSLOT;
Mike McCormack2ab6a772005-03-30 19:02:15 +0000472}
473
474static struct fd *mail_writer_get_fd( struct object *obj )
475{
476 struct mail_writer *writer = (struct mail_writer *) obj;
Alexandre Julliard72ff2bf2007-04-12 20:19:28 +0200477 return (struct fd *)grab_object( writer->fd );
Mike McCormack2ab6a772005-03-30 19:02:15 +0000478}
479
Alexandre Julliarda510a7e2005-12-12 16:46:17 +0100480static unsigned int mail_writer_map_access( struct object *obj, unsigned int access )
481{
Alexandre Julliard806bb492007-03-22 16:36:54 +0100482 /* mailslot writers can only get write access */
Alexandre Julliarda510a7e2005-12-12 16:46:17 +0100483 if (access & GENERIC_WRITE) access |= FILE_GENERIC_WRITE;
Alexandre Julliard806bb492007-03-22 16:36:54 +0100484 if (access & GENERIC_ALL) access |= FILE_GENERIC_WRITE;
Alexandre Julliarda510a7e2005-12-12 16:46:17 +0100485 return access & ~(GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL);
486}
487
Mike McCormack2ab6a772005-03-30 19:02:15 +0000488static struct mailslot *get_mailslot_obj( struct process *process, obj_handle_t handle,
489 unsigned int access )
490{
Vitaliy Margolencf21d4d2005-12-05 13:30:26 +0100491 return (struct mailslot *)get_handle_obj( process, handle, access, &mailslot_ops );
Mike McCormack2ab6a772005-03-30 19:02:15 +0000492}
493
494
495/* create a mailslot */
496DECL_HANDLER(create_mailslot)
497{
498 struct mailslot *mailslot;
Alexandre Julliardead9b062005-11-18 16:31:18 +0000499 struct unicode_str name;
Vitaliy Margolencf21d4d2005-12-05 13:30:26 +0100500 struct directory *root = NULL;
Mike McCormack2ab6a772005-03-30 19:02:15 +0000501
502 reply->handle = 0;
Alexandre Julliardead9b062005-11-18 16:31:18 +0000503 get_req_unicode_str( &name );
Vitaliy Margolencf21d4d2005-12-05 13:30:26 +0100504 if (req->rootdir && !(root = get_directory_obj( current->process, req->rootdir, 0 )))
505 return;
506
507 if ((mailslot = create_mailslot( root, &name, req->attributes, req->max_msgsize,
508 req->read_timeout )))
Mike McCormack2ab6a772005-03-30 19:02:15 +0000509 {
Alexandre Julliard24560e72005-12-09 13:58:25 +0100510 reply->handle = alloc_handle( current->process, mailslot, req->access, req->attributes );
Mike McCormack2ab6a772005-03-30 19:02:15 +0000511 release_object( mailslot );
512 }
Vitaliy Margolencf21d4d2005-12-05 13:30:26 +0100513
514 if (root) release_object( root );
Mike McCormack2ab6a772005-03-30 19:02:15 +0000515}
516
517
Mike McCormack2ab6a772005-03-30 19:02:15 +0000518/* set mailslot information */
519DECL_HANDLER(set_mailslot_info)
520{
521 struct mailslot *mailslot = get_mailslot_obj( current->process, req->handle, 0 );
522
Robert Shearman37957092005-06-10 19:54:46 +0000523 if (mailslot)
Mike McCormack2ab6a772005-03-30 19:02:15 +0000524 {
Robert Shearman37957092005-06-10 19:54:46 +0000525 if (req->flags & MAILSLOT_SET_READ_TIMEOUT)
Mike McCormack2ab6a772005-03-30 19:02:15 +0000526 mailslot->read_timeout = req->read_timeout;
527 reply->max_msgsize = mailslot->max_msgsize;
528 reply->read_timeout = mailslot->read_timeout;
Mike McCormack2ab6a772005-03-30 19:02:15 +0000529 release_object( mailslot );
530 }
531}