mailslot.c 20 KB

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