mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-02-03 04:50:23 +08:00
723f38b10a
This encapsulated creation, duplication, and closing of all Windows objects connected to the message queue in the fhandler. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
182 lines
5.1 KiB
C++
182 lines
5.1 KiB
C++
/* fhandler_mqueue.cc: fhandler for POSIX message queue
|
|
|
|
This file is part of Cygwin.
|
|
|
|
This software is a copyrighted work licensed under the terms of the
|
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
|
details. */
|
|
|
|
#include "winsup.h"
|
|
#include "shared_info.h"
|
|
#include "path.h"
|
|
#include "fhandler.h"
|
|
#include "dtable.h"
|
|
|
|
fhandler_mqueue::fhandler_mqueue () :
|
|
fhandler_base ()
|
|
{
|
|
nohandle (true);
|
|
close_on_exec (true);
|
|
}
|
|
|
|
struct mq_info *
|
|
fhandler_mqueue::_mqinfo (HANDLE fh, SIZE_T filesize, mode_t mode, int flags,
|
|
bool just_open)
|
|
{
|
|
WCHAR buf[NAME_MAX + sizeof ("mqueue/XXX")];
|
|
UNICODE_STRING uname;
|
|
OBJECT_ATTRIBUTES attr;
|
|
NTSTATUS status;
|
|
LARGE_INTEGER fsiz = { QuadPart: (LONGLONG) filesize };
|
|
PVOID mptr = NULL;
|
|
|
|
/* Set sectsize prior to using filesize in NtMapViewOfSection. It will
|
|
get pagesize aligned, which breaks the next NtMapViewOfSection in fork. */
|
|
mqinfo ()->mqi_sectsize = filesize;
|
|
mqinfo ()->mqi_mode = mode;
|
|
mqinfo ()->mqi_flags = flags;
|
|
|
|
__small_swprintf (buf, L"mqueue/mtx%s", get_name ());
|
|
RtlInitUnicodeString (&uname, buf);
|
|
InitializeObjectAttributes (&attr, &uname, OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
|
|
get_shared_parent_dir (),
|
|
everyone_sd (CYG_MUTANT_ACCESS));
|
|
status = NtCreateMutant (&mqinfo ()->mqi_lock, CYG_MUTANT_ACCESS, &attr,
|
|
FALSE);
|
|
if (!NT_SUCCESS (status))
|
|
goto err;
|
|
|
|
wcsncpy (buf + 7, L"snd", 3);
|
|
/* same length, no RtlInitUnicodeString required */
|
|
InitializeObjectAttributes (&attr, &uname, OBJ_OPENIF | OBJ_CASE_INSENSITIVE,
|
|
get_shared_parent_dir (),
|
|
everyone_sd (CYG_EVENT_ACCESS));
|
|
status = NtCreateEvent (&mqinfo ()->mqi_waitsend, CYG_EVENT_ACCESS, &attr,
|
|
NotificationEvent, FALSE);
|
|
if (!NT_SUCCESS (status))
|
|
goto err;
|
|
wcsncpy (buf + 7, L"rcv", 3);
|
|
/* same length, same attributes, no more init required */
|
|
status = NtCreateEvent (&mqinfo ()->mqi_waitrecv, CYG_EVENT_ACCESS, &attr,
|
|
NotificationEvent, FALSE);
|
|
if (!NT_SUCCESS (status))
|
|
goto err;
|
|
|
|
InitializeObjectAttributes (&attr, NULL, 0, NULL, NULL);
|
|
status = NtCreateSection (&mqinfo ()->mqi_sect, SECTION_ALL_ACCESS, &attr,
|
|
&fsiz, PAGE_READWRITE, SEC_COMMIT, fh);
|
|
if (!NT_SUCCESS (status))
|
|
goto err;
|
|
|
|
status = NtMapViewOfSection (mqinfo ()->mqi_sect, NtCurrentProcess (),
|
|
&mptr, 0, filesize, NULL, &filesize,
|
|
ViewShare, 0, PAGE_READWRITE);
|
|
if (!NT_SUCCESS (status))
|
|
goto err;
|
|
|
|
mqinfo ()->mqi_hdr = (struct mq_hdr *) mptr;
|
|
|
|
/* Special problem on Cygwin. /dev/mqueue is just a simple dir,
|
|
so there's a chance normal files are created in there. */
|
|
if (just_open && mqinfo ()->mqi_hdr->mqh_magic != MQI_MAGIC)
|
|
{
|
|
status = STATUS_ACCESS_DENIED;
|
|
goto err;
|
|
}
|
|
|
|
mqinfo ()->mqi_magic = MQI_MAGIC;
|
|
return mqinfo ();
|
|
|
|
err:
|
|
if (mqinfo ()->mqi_sect)
|
|
NtClose (mqinfo ()->mqi_sect);
|
|
if (mqinfo ()->mqi_waitrecv)
|
|
NtClose (mqinfo ()->mqi_waitrecv);
|
|
if (mqinfo ()->mqi_waitsend)
|
|
NtClose (mqinfo ()->mqi_waitsend);
|
|
if (mqinfo ()->mqi_lock)
|
|
NtClose (mqinfo ()->mqi_lock);
|
|
__seterrno_from_nt_status (status);
|
|
return NULL;
|
|
}
|
|
|
|
char *
|
|
fhandler_mqueue::get_proc_fd_name (char *buf)
|
|
{
|
|
return strcpy (buf, get_name ());
|
|
}
|
|
|
|
int __reg2
|
|
fhandler_mqueue::fstat (struct stat *buf)
|
|
{
|
|
int ret = fhandler_base::fstat (buf);
|
|
if (!ret)
|
|
{
|
|
buf->st_mode = S_IFREG | mqinfo ()->mqi_mode;
|
|
buf->st_dev = FH_MQUEUE;
|
|
buf->st_ino = hash_path_name (0, get_name ());
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int
|
|
fhandler_mqueue::dup (fhandler_base *child, int flags)
|
|
{
|
|
/* FIXME */
|
|
set_errno (EBADF);
|
|
return -1;
|
|
}
|
|
|
|
void
|
|
fhandler_mqueue::fixup_after_fork (HANDLE parent)
|
|
{
|
|
__try
|
|
{
|
|
PVOID mptr = NULL;
|
|
SIZE_T filesize = mqinfo ()->mqi_sectsize;
|
|
NTSTATUS status;
|
|
|
|
DuplicateHandle (parent, mqinfo ()->mqi_sect,
|
|
GetCurrentProcess (), &mqinfo ()->mqi_sect,
|
|
0, FALSE, DUPLICATE_SAME_ACCESS);
|
|
status = NtMapViewOfSection (mqinfo ()->mqi_sect, NtCurrentProcess (),
|
|
&mptr, 0, filesize, NULL, &filesize,
|
|
ViewShare, 0, PAGE_READWRITE);
|
|
if (!NT_SUCCESS (status))
|
|
api_fatal ("Mapping message queue failed in fork\n");
|
|
else
|
|
mqinfo ()->mqi_hdr = (struct mq_hdr *) mptr;
|
|
DuplicateHandle (parent, mqinfo ()->mqi_waitsend,
|
|
GetCurrentProcess (), &mqinfo ()->mqi_waitsend,
|
|
0, FALSE, DUPLICATE_SAME_ACCESS);
|
|
DuplicateHandle (parent, mqinfo ()->mqi_waitrecv,
|
|
GetCurrentProcess (), &mqinfo ()->mqi_waitrecv,
|
|
0, FALSE, DUPLICATE_SAME_ACCESS);
|
|
DuplicateHandle (parent, mqinfo ()->mqi_lock,
|
|
GetCurrentProcess (), &mqinfo ()->mqi_lock,
|
|
0, FALSE, DUPLICATE_SAME_ACCESS);
|
|
}
|
|
__except (EFAULT) {}
|
|
__endtry
|
|
}
|
|
|
|
int
|
|
fhandler_mqueue::close ()
|
|
{
|
|
int ret = -1;
|
|
|
|
__try
|
|
{
|
|
mqinfo ()->mqi_magic = 0; /* just in case */
|
|
NtUnmapViewOfSection (NtCurrentProcess (), mqinfo ()->mqi_hdr);
|
|
NtClose (mqinfo ()->mqi_sect);
|
|
NtClose (mqinfo ()->mqi_waitsend);
|
|
NtClose (mqinfo ()->mqi_waitrecv);
|
|
NtClose (mqinfo ()->mqi_lock);
|
|
ret = 0;
|
|
}
|
|
__except (EFAULT) {}
|
|
__endtry
|
|
return ret;
|
|
}
|