mailslot.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595
  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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  20. *
  21. */
  22. #include "config.h"
  23. #include "wine/port.h"
  24. #include "ntstatus.h"
  25. #define WIN32_NO_STATUS
  26. #include <assert.h>
  27. #include <fcntl.h>
  28. #include <string.h>
  29. #include <stdarg.h>
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <sys/time.h>
  33. #include <sys/types.h>
  34. #ifdef HAVE_SYS_IOCTL_H
  35. #include <sys/ioctl.h>
  36. #endif
  37. #ifdef HAVE_SYS_SOCKET_H
  38. #include <sys/socket.h>
  39. #endif
  40. #ifdef HAVE_SYS_FILIO_H
  41. #include <sys/filio.h>
  42. #endif
  43. #include "windef.h"
  44. #include "winternl.h"
  45. #include "file.h"
  46. #include "handle.h"
  47. #include "thread.h"
  48. #include "request.h"
  49. struct mailslot
  50. {
  51. struct object obj;
  52. struct fd *fd;
  53. int write_fd;
  54. unsigned int max_msgsize;
  55. timeout_t read_timeout;
  56. struct list writers;
  57. };
  58. /* mailslot functions */
  59. static void mailslot_dump( struct object*, int );
  60. static struct fd *mailslot_get_fd( struct object * );
  61. static unsigned int mailslot_map_access( struct object *obj, unsigned int access );
  62. static int mailslot_link_name( struct object *obj, struct object_name *name, struct object *parent );
  63. static struct object *mailslot_open_file( struct object *obj, unsigned int access,
  64. unsigned int sharing, unsigned int options );
  65. static void mailslot_destroy( struct object * );
  66. static const struct object_ops mailslot_ops =
  67. {
  68. sizeof(struct mailslot), /* size */
  69. &file_type, /* type */
  70. mailslot_dump, /* dump */
  71. add_queue, /* add_queue */
  72. remove_queue, /* remove_queue */
  73. default_fd_signaled, /* signaled */
  74. no_satisfied, /* satisfied */
  75. no_signal, /* signal */
  76. mailslot_get_fd, /* get_fd */
  77. mailslot_map_access, /* map_access */
  78. default_get_sd, /* get_sd */
  79. default_set_sd, /* set_sd */
  80. default_get_full_name, /* get_full_name */
  81. no_lookup_name, /* lookup_name */
  82. mailslot_link_name, /* link_name */
  83. default_unlink_name, /* unlink_name */
  84. mailslot_open_file, /* open_file */
  85. no_kernel_obj_list, /* get_kernel_obj_list */
  86. no_close_handle, /* close_handle */
  87. mailslot_destroy /* destroy */
  88. };
  89. static enum server_fd_type mailslot_get_fd_type( struct fd *fd );
  90. static void mailslot_queue_async( struct fd *fd, struct async *async, int type, int count );
  91. static const struct fd_ops mailslot_fd_ops =
  92. {
  93. default_fd_get_poll_events, /* get_poll_events */
  94. default_poll_event, /* poll_event */
  95. mailslot_get_fd_type, /* get_fd_type */
  96. no_fd_read, /* read */
  97. no_fd_write, /* write */
  98. no_fd_flush, /* flush */
  99. default_fd_get_file_info, /* get_file_info */
  100. no_fd_get_volume_info, /* get_volume_info */
  101. default_fd_ioctl, /* ioctl */
  102. mailslot_queue_async, /* queue_async */
  103. default_fd_reselect_async /* reselect_async */
  104. };
  105. struct mail_writer
  106. {
  107. struct object obj;
  108. struct fd *fd;
  109. struct mailslot *mailslot;
  110. struct list entry;
  111. unsigned int access;
  112. unsigned int sharing;
  113. };
  114. static void mail_writer_dump( struct object *obj, int verbose );
  115. static struct fd *mail_writer_get_fd( struct object *obj );
  116. static unsigned int mail_writer_map_access( struct object *obj, unsigned int access );
  117. static void mail_writer_destroy( struct object *obj);
  118. static const struct object_ops mail_writer_ops =
  119. {
  120. sizeof(struct mail_writer), /* size */
  121. &file_type, /* type */
  122. mail_writer_dump, /* dump */
  123. no_add_queue, /* add_queue */
  124. NULL, /* remove_queue */
  125. NULL, /* signaled */
  126. NULL, /* satisfied */
  127. no_signal, /* signal */
  128. mail_writer_get_fd, /* get_fd */
  129. mail_writer_map_access, /* map_access */
  130. default_get_sd, /* get_sd */
  131. default_set_sd, /* set_sd */
  132. no_get_full_name, /* get_full_name */
  133. no_lookup_name, /* lookup_name */
  134. no_link_name, /* link_name */
  135. NULL, /* unlink_name */
  136. no_open_file, /* open_file */
  137. no_kernel_obj_list, /* get_kernel_obj_list */
  138. no_close_handle, /* close_handle */
  139. mail_writer_destroy /* destroy */
  140. };
  141. static enum server_fd_type mail_writer_get_fd_type( struct fd *fd );
  142. static const struct fd_ops mail_writer_fd_ops =
  143. {
  144. default_fd_get_poll_events, /* get_poll_events */
  145. default_poll_event, /* poll_event */
  146. mail_writer_get_fd_type, /* get_fd_type */
  147. no_fd_read, /* read */
  148. no_fd_write, /* write */
  149. no_fd_flush, /* flush */
  150. default_fd_get_file_info, /* get_file_info */
  151. no_fd_get_volume_info, /* get_volume_info */
  152. default_fd_ioctl, /* ioctl */
  153. default_fd_queue_async, /* queue_async */
  154. default_fd_reselect_async /* reselect_async */
  155. };
  156. struct mailslot_device
  157. {
  158. struct object obj; /* object header */
  159. struct namespace *mailslots; /* mailslot namespace */
  160. };
  161. struct mailslot_device_file
  162. {
  163. struct object obj; /* object header */
  164. struct fd *fd; /* pseudo-fd for ioctls */
  165. struct mailslot_device *device; /* mailslot device */
  166. };
  167. static void mailslot_device_dump( struct object *obj, int verbose );
  168. static struct object *mailslot_device_lookup_name( struct object *obj, struct unicode_str *name,
  169. unsigned int attr, struct object *root );
  170. static struct object *mailslot_device_open_file( struct object *obj, unsigned int access,
  171. unsigned int sharing, unsigned int options );
  172. static void mailslot_device_destroy( struct object *obj );
  173. static const struct object_ops mailslot_device_ops =
  174. {
  175. sizeof(struct mailslot_device), /* size */
  176. &device_type, /* type */
  177. mailslot_device_dump, /* dump */
  178. no_add_queue, /* add_queue */
  179. NULL, /* remove_queue */
  180. NULL, /* signaled */
  181. no_satisfied, /* satisfied */
  182. no_signal, /* signal */
  183. no_get_fd, /* get_fd */
  184. default_map_access, /* map_access */
  185. default_get_sd, /* get_sd */
  186. default_set_sd, /* set_sd */
  187. default_get_full_name, /* get_full_name */
  188. mailslot_device_lookup_name, /* lookup_name */
  189. directory_link_name, /* link_name */
  190. default_unlink_name, /* unlink_name */
  191. mailslot_device_open_file, /* open_file */
  192. no_kernel_obj_list, /* get_kernel_obj_list */
  193. no_close_handle, /* close_handle */
  194. mailslot_device_destroy /* destroy */
  195. };
  196. static void mailslot_device_file_dump( struct object *obj, int verbose );
  197. static struct fd *mailslot_device_file_get_fd( struct object *obj );
  198. static WCHAR *mailslot_device_file_get_full_name( struct object *obj, data_size_t *len );
  199. static void mailslot_device_file_destroy( struct object *obj );
  200. static enum server_fd_type mailslot_device_file_get_fd_type( struct fd *fd );
  201. static const struct object_ops mailslot_device_file_ops =
  202. {
  203. sizeof(struct mailslot_device_file), /* size */
  204. &file_type, /* type */
  205. mailslot_device_file_dump, /* dump */
  206. add_queue, /* add_queue */
  207. remove_queue, /* remove_queue */
  208. default_fd_signaled, /* signaled */
  209. no_satisfied, /* satisfied */
  210. no_signal, /* signal */
  211. mailslot_device_file_get_fd, /* get_fd */
  212. default_map_access, /* map_access */
  213. default_get_sd, /* get_sd */
  214. default_set_sd, /* set_sd */
  215. mailslot_device_file_get_full_name, /* get_full_name */
  216. no_lookup_name, /* lookup_name */
  217. no_link_name, /* link_name */
  218. NULL, /* unlink_name */
  219. no_open_file, /* open_file */
  220. no_kernel_obj_list, /* get_kernel_obj_list */
  221. no_close_handle, /* close_handle */
  222. mailslot_device_file_destroy /* destroy */
  223. };
  224. static const struct fd_ops mailslot_device_fd_ops =
  225. {
  226. default_fd_get_poll_events, /* get_poll_events */
  227. default_poll_event, /* poll_event */
  228. mailslot_device_file_get_fd_type, /* get_fd_type */
  229. no_fd_read, /* read */
  230. no_fd_write, /* write */
  231. no_fd_flush, /* flush */
  232. default_fd_get_file_info, /* get_file_info */
  233. no_fd_get_volume_info, /* get_volume_info */
  234. default_fd_ioctl, /* ioctl */
  235. default_fd_queue_async, /* queue_async */
  236. default_fd_reselect_async /* reselect_async */
  237. };
  238. static void mailslot_destroy( struct object *obj)
  239. {
  240. struct mailslot *mailslot = (struct mailslot *) obj;
  241. assert( mailslot->fd );
  242. if (mailslot->write_fd != -1)
  243. {
  244. shutdown( mailslot->write_fd, SHUT_RDWR );
  245. close( mailslot->write_fd );
  246. }
  247. release_object( mailslot->fd );
  248. }
  249. static void mailslot_dump( struct object *obj, int verbose )
  250. {
  251. struct mailslot *mailslot = (struct mailslot *) obj;
  252. assert( obj->ops == &mailslot_ops );
  253. fprintf( stderr, "Mailslot max_msgsize=%d read_timeout=%s\n",
  254. mailslot->max_msgsize, get_timeout_str(mailslot->read_timeout) );
  255. }
  256. static enum server_fd_type mailslot_get_fd_type( struct fd *fd )
  257. {
  258. return FD_TYPE_MAILSLOT;
  259. }
  260. static struct fd *mailslot_get_fd( struct object *obj )
  261. {
  262. struct mailslot *mailslot = (struct mailslot *) obj;
  263. return (struct fd *)grab_object( mailslot->fd );
  264. }
  265. static unsigned int mailslot_map_access( struct object *obj, unsigned int access )
  266. {
  267. /* mailslots can only be read */
  268. return default_map_access( obj, access ) & FILE_GENERIC_READ;
  269. }
  270. static int mailslot_link_name( struct object *obj, struct object_name *name, struct object *parent )
  271. {
  272. struct mailslot_device *dev = (struct mailslot_device *)parent;
  273. if (parent->ops != &mailslot_device_ops)
  274. {
  275. set_error( STATUS_OBJECT_NAME_INVALID );
  276. return 0;
  277. }
  278. namespace_add( dev->mailslots, name );
  279. name->parent = grab_object( parent );
  280. return 1;
  281. }
  282. static struct object *mailslot_open_file( struct object *obj, unsigned int access,
  283. unsigned int sharing, unsigned int options )
  284. {
  285. struct mailslot *mailslot = (struct mailslot *)obj;
  286. struct mail_writer *writer;
  287. int unix_fd;
  288. if (!(sharing & FILE_SHARE_READ))
  289. {
  290. set_error( STATUS_SHARING_VIOLATION );
  291. return NULL;
  292. }
  293. if (!list_empty( &mailslot->writers ))
  294. {
  295. /* Readers and writers cannot be mixed.
  296. * If there's more than one writer, all writers must open with FILE_SHARE_WRITE
  297. */
  298. writer = LIST_ENTRY( list_head(&mailslot->writers), struct mail_writer, entry );
  299. if (((access & (GENERIC_WRITE|FILE_WRITE_DATA)) || (writer->access & FILE_WRITE_DATA)) &&
  300. !((sharing & FILE_SHARE_WRITE) && (writer->sharing & FILE_SHARE_WRITE)))
  301. {
  302. set_error( STATUS_SHARING_VIOLATION );
  303. return NULL;
  304. }
  305. }
  306. if ((unix_fd = dup( mailslot->write_fd )) == -1)
  307. {
  308. file_set_error();
  309. return NULL;
  310. }
  311. if (!(writer = alloc_object( &mail_writer_ops )))
  312. {
  313. close( unix_fd );
  314. return NULL;
  315. }
  316. grab_object( mailslot );
  317. writer->mailslot = mailslot;
  318. writer->access = mail_writer_map_access( &writer->obj, access );
  319. writer->sharing = sharing;
  320. list_add_head( &mailslot->writers, &writer->entry );
  321. if (!(writer->fd = create_anonymous_fd( &mail_writer_fd_ops, unix_fd, &writer->obj, options )))
  322. {
  323. release_object( writer );
  324. return NULL;
  325. }
  326. allow_fd_caching( writer->fd );
  327. return &writer->obj;
  328. }
  329. static void mailslot_queue_async( struct fd *fd, struct async *async, int type, int count )
  330. {
  331. struct mailslot *mailslot = get_fd_user( fd );
  332. assert(mailslot->obj.ops == &mailslot_ops);
  333. fd_queue_async( fd, async, type );
  334. async_set_timeout( async, mailslot->read_timeout ? mailslot->read_timeout : -1,
  335. STATUS_IO_TIMEOUT );
  336. set_error( STATUS_PENDING );
  337. }
  338. static void mailslot_device_dump( struct object *obj, int verbose )
  339. {
  340. fputs( "Mailslot device\n", stderr );
  341. }
  342. static struct object *mailslot_device_lookup_name( struct object *obj, struct unicode_str *name,
  343. unsigned int attr, struct object *root )
  344. {
  345. struct mailslot_device *device = (struct mailslot_device*)obj;
  346. struct object *found;
  347. assert( obj->ops == &mailslot_device_ops );
  348. if (!name) return NULL; /* open the device itself */
  349. if ((found = find_object( device->mailslots, name, attr | OBJ_CASE_INSENSITIVE )))
  350. name->len = 0;
  351. return found;
  352. }
  353. static struct object *mailslot_device_open_file( struct object *obj, unsigned int access,
  354. unsigned int sharing, unsigned int options )
  355. {
  356. struct mailslot_device_file *file;
  357. if (!(file = alloc_object( &mailslot_device_file_ops ))) return NULL;
  358. file->device = (struct mailslot_device *)grab_object( obj );
  359. if (!(file->fd = alloc_pseudo_fd( &mailslot_device_fd_ops, obj, options )))
  360. {
  361. release_object( file );
  362. return NULL;
  363. }
  364. allow_fd_caching( file->fd );
  365. return &file->obj;
  366. }
  367. static void mailslot_device_destroy( struct object *obj )
  368. {
  369. struct mailslot_device *device = (struct mailslot_device*)obj;
  370. assert( obj->ops == &mailslot_device_ops );
  371. free( device->mailslots );
  372. }
  373. struct object *create_mailslot_device( struct object *root, const struct unicode_str *name,
  374. unsigned int attr, const struct security_descriptor *sd )
  375. {
  376. struct mailslot_device *dev;
  377. if ((dev = create_named_object( root, &mailslot_device_ops, name, attr, sd )) &&
  378. get_error() != STATUS_OBJECT_NAME_EXISTS)
  379. {
  380. dev->mailslots = NULL;
  381. if (!(dev->mailslots = create_namespace( 7 )))
  382. {
  383. release_object( dev );
  384. dev = NULL;
  385. }
  386. }
  387. return &dev->obj;
  388. }
  389. static void mailslot_device_file_dump( struct object *obj, int verbose )
  390. {
  391. struct mailslot_device_file *file = (struct mailslot_device_file *)obj;
  392. fprintf( stderr, "File on mailslot device %p\n", file->device );
  393. }
  394. static struct fd *mailslot_device_file_get_fd( struct object *obj )
  395. {
  396. struct mailslot_device_file *file = (struct mailslot_device_file *)obj;
  397. return (struct fd *)grab_object( file->fd );
  398. }
  399. static WCHAR *mailslot_device_file_get_full_name( struct object *obj, data_size_t *len )
  400. {
  401. struct mailslot_device_file *file = (struct mailslot_device_file *)obj;
  402. return file->device->obj.ops->get_full_name( &file->device->obj, len );
  403. }
  404. static void mailslot_device_file_destroy( struct object *obj )
  405. {
  406. struct mailslot_device_file *file = (struct mailslot_device_file*)obj;
  407. assert( obj->ops == &mailslot_device_file_ops );
  408. if (file->fd) release_object( file->fd );
  409. release_object( file->device );
  410. }
  411. static enum server_fd_type mailslot_device_file_get_fd_type( struct fd *fd )
  412. {
  413. return FD_TYPE_DEVICE;
  414. }
  415. static struct mailslot *create_mailslot( struct object *root,
  416. const struct unicode_str *name, unsigned int attr,
  417. int max_msgsize, timeout_t read_timeout,
  418. const struct security_descriptor *sd )
  419. {
  420. struct mailslot *mailslot;
  421. int fds[2];
  422. if (!(mailslot = create_named_object( root, &mailslot_ops, name, attr, sd ))) return NULL;
  423. mailslot->fd = NULL;
  424. mailslot->write_fd = -1;
  425. mailslot->max_msgsize = max_msgsize;
  426. mailslot->read_timeout = read_timeout;
  427. list_init( &mailslot->writers );
  428. if (!socketpair( PF_UNIX, SOCK_DGRAM, 0, fds ))
  429. {
  430. fcntl( fds[0], F_SETFL, O_NONBLOCK );
  431. fcntl( fds[1], F_SETFL, O_NONBLOCK );
  432. shutdown( fds[0], SHUT_RD );
  433. mailslot->write_fd = fds[0];
  434. if ((mailslot->fd = create_anonymous_fd( &mailslot_fd_ops, fds[1], &mailslot->obj,
  435. FILE_SYNCHRONOUS_IO_NONALERT )))
  436. {
  437. allow_fd_caching( mailslot->fd );
  438. return mailslot;
  439. }
  440. }
  441. else file_set_error();
  442. release_object( mailslot );
  443. return NULL;
  444. }
  445. static void mail_writer_dump( struct object *obj, int verbose )
  446. {
  447. fprintf( stderr, "Mailslot writer\n" );
  448. }
  449. static void mail_writer_destroy( struct object *obj)
  450. {
  451. struct mail_writer *writer = (struct mail_writer *) obj;
  452. if (writer->fd) release_object( writer->fd );
  453. list_remove( &writer->entry );
  454. release_object( writer->mailslot );
  455. }
  456. static enum server_fd_type mail_writer_get_fd_type( struct fd *fd )
  457. {
  458. return FD_TYPE_MAILSLOT;
  459. }
  460. static struct fd *mail_writer_get_fd( struct object *obj )
  461. {
  462. struct mail_writer *writer = (struct mail_writer *) obj;
  463. return (struct fd *)grab_object( writer->fd );
  464. }
  465. static unsigned int mail_writer_map_access( struct object *obj, unsigned int access )
  466. {
  467. /* mailslot writers can only get write access */
  468. return default_map_access( obj, access ) & FILE_GENERIC_WRITE;
  469. }
  470. static struct mailslot *get_mailslot_obj( struct process *process, obj_handle_t handle,
  471. unsigned int access )
  472. {
  473. return (struct mailslot *)get_handle_obj( process, handle, access, &mailslot_ops );
  474. }
  475. /* create a mailslot */
  476. DECL_HANDLER(create_mailslot)
  477. {
  478. struct mailslot *mailslot;
  479. struct unicode_str name;
  480. struct object *root;
  481. const struct security_descriptor *sd;
  482. const struct object_attributes *objattr = get_req_object_attributes( &sd, &name, &root );
  483. if (!objattr) return;
  484. if (!name.len) /* mailslots need a root directory even without a name */
  485. {
  486. if (!objattr->rootdir)
  487. {
  488. set_error( STATUS_OBJECT_PATH_SYNTAX_BAD );
  489. return;
  490. }
  491. if (!(root = get_directory_obj( current->process, objattr->rootdir ))) return;
  492. }
  493. if ((mailslot = create_mailslot( root, &name, objattr->attributes, req->max_msgsize,
  494. req->read_timeout, sd )))
  495. {
  496. reply->handle = alloc_handle( current->process, mailslot, req->access, objattr->attributes );
  497. release_object( mailslot );
  498. }
  499. if (root) release_object( root );
  500. }
  501. /* set mailslot information */
  502. DECL_HANDLER(set_mailslot_info)
  503. {
  504. struct mailslot *mailslot = get_mailslot_obj( current->process, req->handle, 0 );
  505. if (mailslot)
  506. {
  507. if (req->flags & MAILSLOT_SET_READ_TIMEOUT)
  508. mailslot->read_timeout = req->read_timeout;
  509. reply->max_msgsize = mailslot->max_msgsize;
  510. reply->read_timeout = mailslot->read_timeout;
  511. release_object( mailslot );
  512. }
  513. }