summaryrefslogtreecommitdiffhomepage
path: root/src/msq/ntapi_msq_connect.c
diff options
context:
space:
mode:
authormidipix <writeonce@midipix.org>2017-09-08 22:22:22 +0000
committermidipix <writeonce@midipix.org>2017-09-08 22:49:30 -0400
commit47f21a54cf74e2ec0fc7aa7e3ee06ab5087600a6 (patch)
tree99d6b4aa390f16e0891877479e5adb4de005d59d /src/msq/ntapi_msq_connect.c
parenta6563a605d7906252921503e89eae8da00eb599c (diff)
downloadntapi-47f21a54cf74e2ec0fc7aa7e3ee06ab5087600a6.tar.bz2
ntapi-47f21a54cf74e2ec0fc7aa7e3ee06ab5087600a6.tar.xz
integrated msgqueue client side interfaces.
Diffstat (limited to 'src/msq/ntapi_msq_connect.c')
-rw-r--r--src/msq/ntapi_msq_connect.c353
1 files changed, 353 insertions, 0 deletions
diff --git a/src/msq/ntapi_msq_connect.c b/src/msq/ntapi_msq_connect.c
new file mode 100644
index 0000000..c4a0f98
--- /dev/null
+++ b/src/msq/ntapi_msq_connect.c
@@ -0,0 +1,353 @@
+/********************************************************/
+/* ntapi: Native API core library */
+/* Copyright (C) 2013--2017 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
+/********************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <ntapi/nt_file.h>
+#include <ntapi/nt_string.h>
+#include <ntapi/nt_atomic.h>
+#include <ntapi/nt_port.h>
+#include <ntapi/nt_ipc.h>
+#include <ntapi/nt_msq.h>
+#include <ntapi/ntapi.h>
+#include "ntapi_impl.h"
+
+static const nt_guid g_msqpid = NT_IPC_GUID_MSQPID;
+static const wchar16_t p_msqpid[6] = NT_IPC_OBJDIR_PREFIX_MSQPID;
+
+static int32_t __msqctl_get_service_attr(
+ nt_rtdata * rtdata,
+ nt_tty_service_info * msqctl)
+{
+ nt_iosb iosb;
+
+ /* inherited runtime data? */
+ if (rtdata->msqctl_keys[0]) {
+ msqctl->attr.ver_major = 0;
+ msqctl->attr.ver_minor = 0;
+ msqctl->attr.options = 0;
+ msqctl->attr.flags = 0;
+
+ msqctl->attr.type = rtdata->msqctl_type;
+ msqctl->attr.subtype = rtdata->msqctl_subtype;
+
+ msqctl->attr.keys.key[0] = rtdata->msqctl_keys[0];
+ msqctl->attr.keys.key[1] = rtdata->msqctl_keys[1];
+ msqctl->attr.keys.key[2] = rtdata->msqctl_keys[2];
+ msqctl->attr.keys.key[3] = rtdata->msqctl_keys[3];
+ msqctl->attr.keys.key[4] = rtdata->msqctl_keys[4];
+ msqctl->attr.keys.key[5] = rtdata->msqctl_keys[5];
+
+ __ntapi->tt_guid_copy(
+ &msqctl->attr.guid,
+ &rtdata->msqctl_guid);
+
+ return NT_STATUS_SUCCESS;
+ }
+
+ /* obtain service info */
+ return __ntapi->tty_query_information_service(
+ 0,&iosb,msqctl,
+ &(nt_guid)NT_PORT_GUID_MSQCTL,
+ 0,0);
+}
+
+static int32_t __msqctl_server_connect(
+ nt_rtdata * rtdata,
+ nt_tty_service_info * msqctl)
+{
+ int32_t status;
+
+ /* already cononected? */
+ if (rtdata->hmsqctl)
+ return NT_STATUS_SUCCESS;
+
+ /* connect */
+ if ((status = __ntapi->ipc_connect_by_attr(
+ &rtdata->hmsqctl,
+ &msqctl->attr)))
+ return status;
+
+ /* update */
+ rtdata->msqctl_type = msqctl->attr.type;
+ rtdata->msqctl_subtype = msqctl->attr.subtype;
+
+ rtdata->msqctl_keys[0] = msqctl->attr.keys.key[0];
+ rtdata->msqctl_keys[1] = msqctl->attr.keys.key[1];
+ rtdata->msqctl_keys[2] = msqctl->attr.keys.key[2];
+ rtdata->msqctl_keys[3] = msqctl->attr.keys.key[3];
+ rtdata->msqctl_keys[4] = msqctl->attr.keys.key[4];
+ rtdata->msqctl_keys[5] = msqctl->attr.keys.key[5];
+
+ __ntapi->tt_guid_copy(
+ &rtdata->msqctl_guid,
+ &msqctl->attr.guid);
+
+ return NT_STATUS_SUCCESS;
+}
+
+static int32_t __msqpid_symlink_set(
+ nt_rtdata * rtdata,
+ nt_tty_service_info * msqctl)
+{
+ int32_t status;
+ void * hpiddir;
+ nt_port_name svcname;
+ nt_unicode_string str;
+
+ if (rtdata->hmsqpid)
+ return NT_STATUS_SUCCESS;
+
+ if (!rtdata->hmsqpiddir) {
+ if ((status = __ntapi->tt_open_ipc_object_directory(
+ &hpiddir,
+ NT_DIRECTORY_ALL_ACCESS,
+ p_msqpid,&g_msqpid)))
+ return status;
+
+ if (at_locked_cas((intptr_t *)&rtdata->hmsqpiddir,0,(intptr_t)hpiddir))
+ __ntapi->zw_close(hpiddir);
+ }
+
+ __ntapi->tt_port_name_from_attr(
+ &svcname,&msqctl->attr);
+
+ str.strlen = (uint16_t)(size_t)(&(((nt_port_name *)0)->null_termination));
+ str.maxlen = sizeof(nt_port_name);
+ str.buffer = svcname.base_named_objects;
+
+ return __ntapi->tt_create_ipc_object_directory_entry(
+ &rtdata->hmsqpid,
+ NT_SEC_STANDARD_RIGHTS_ALL,
+ rtdata->hmsqpiddir,
+ 0,&str,
+ pe_get_current_process_id());
+
+}
+
+static int32_t __stdcall __msq_open(
+ void * hipc,
+ nt_msq_info * msq,
+ uint32_t access,
+ nt_object_attributes * oa,
+ nt_iosb * iosb,
+ uint32_t share,
+ uint32_t msqslots,
+ uint32_t key,
+ uint32_t id,
+ uint32_t opcode)
+{
+ int32_t status;
+ nt_tty_port_msg msg;
+ nt_iosb siosb;
+ nt_tty_service_info msqctl;
+ nt_runtime_data * rtdata;
+
+ /* init */
+ rtdata = (__ntapi_internals())->rtdata;
+
+ /* msqctl service attributes */
+ if (!rtdata->hmsqpid)
+ if ((status = __msqctl_get_service_attr(rtdata,&msqctl)))
+ return status;
+
+ /* msqctl server */
+ if ((status = __msqctl_server_connect(rtdata,&msqctl)))
+ return status;
+
+ /* msqpid symlink */
+ if ((status = __msqpid_symlink_set(rtdata,&msqctl)))
+ return status;
+
+ /* hipc */
+ if (!hipc && (opcode == NT_TTY_MSQ_ALLOC))
+ hipc = (__ntapi_internals())->rtdata->hmsqctl;
+
+ /* obtain msq info */
+ __ntapi->tt_aligned_block_memset(
+ &msg,0,sizeof(msg));
+
+ if (!iosb)
+ iosb = &siosb;
+
+ msg.header.msg_type = NT_LPC_NEW_MESSAGE;
+ msg.header.data_size = sizeof(nt_msq_info_msg) - sizeof(msg.header);
+ msg.header.msg_size = sizeof(msg);
+ msg.ttyinfo.opcode = opcode;
+
+ msg.msqinfo.msqkey = (int32_t)key;
+ msg.msqinfo.msqid = (int32_t)id;
+ msg.msqinfo.msqslots = msqslots;
+
+ msg.msqinfo.ntattr = oa->obj_attr;
+ msg.msqinfo.ntaccess = access;
+ msg.msqinfo.ntshare = share;
+
+ if ((status = __ntapi->zw_request_wait_reply_port(hipc,&msg,&msg)))
+ return status;
+ else if (msg.ttyinfo.status)
+ return msg.ttyinfo.status;
+
+ iosb->info = sizeof(msg.svcinfo);
+ iosb->status = NT_STATUS_SUCCESS;
+
+ /* new msqueue? */
+ if (opcode == NT_TTY_MSQ_ALLOC)
+ if ((status = __ntapi->ipc_connect_by_attr(
+ &hipc,&msg.svcinfo.attr)))
+ return status;
+
+ /* all done */
+ __ntapi->tt_aligned_block_memset(
+ (uintptr_t *)msq,
+ 0,sizeof(*msq));
+
+ msq->msqkey = msg.svcinfo.key;
+ msq->msqid = msg.svcinfo.id;
+
+ msq->hport = hipc;
+
+ return NT_STATUS_SUCCESS;
+}
+
+
+int32_t __ntapi_msq_create(
+ __in void * hport,
+ __out nt_msq_info * msq,
+ __in uint32_t access,
+ __in nt_object_attributes * oa,
+ __out nt_iosb * iosb,
+ __in uint32_t share,
+ __in uint32_t nslots)
+{
+ uint32_t key;
+
+ /* validate */
+ if (!oa->root_dir)
+ return NT_STATUS_DIRECTORY_SERVICE_REQUIRED;
+
+ if (oa->obj_name && !oa->obj_name->strlen) {
+ key = 0;
+
+ } else if (oa->obj_name) {
+ if (oa->obj_name->strlen != 8 * sizeof(wchar16_t))
+ return NT_STATUS_OBJECT_NAME_INVALID;
+
+ if (__ntapi->tt_hex_utf16_to_uint32(oa->obj_name->buffer,&key))
+ return NT_STATUS_OBJECT_NAME_INVALID;
+
+ } else {
+ key = 0;
+ }
+
+ /* open msqueue */
+ return __msq_open(
+ hport,msq,access,
+ oa,iosb,share,nslots,
+ key,0,NT_TTY_MSQ_ALLOC);
+}
+
+
+int32_t __stdcall __ntapi_msq_open(
+ __in void * hport,
+ __out nt_msq_info * msq,
+ __in uint32_t access,
+ __in nt_object_attributes * oa,
+ __out nt_iosb * iosb,
+ __in uint32_t share,
+ __in uint32_t nslots)
+{
+ int32_t status;
+ uint32_t key;
+ uint32_t id;
+ void * hsymlink;
+ nt_oa ipcoa;
+ void * hipc;
+ nt_rtdata * rtdata;
+ nt_tty_service_info msqctl;
+
+ /* init */
+ rtdata = (__ntapi_internals())->rtdata;
+
+ /* validate */
+ if (!oa->root_dir)
+ return NT_STATUS_DIRECTORY_SERVICE_REQUIRED;
+
+ if (!oa->obj_name)
+ return NT_STATUS_INVALID_PARAMETER;
+
+ if (oa->obj_name->strlen != 8 * sizeof(wchar16_t))
+ return NT_STATUS_OBJECT_NAME_INVALID;
+
+ if (__ntapi->tt_hex_utf16_to_uint32(oa->obj_name->buffer,&key))
+ return NT_STATUS_OBJECT_NAME_INVALID;
+
+ /* open symlink */
+ ipcoa.len = sizeof(ipcoa);
+ ipcoa.root_dir = oa->root_dir;
+ ipcoa.obj_name = oa->obj_name;
+ ipcoa.obj_attr = 0;
+ ipcoa.sec_desc = oa->sec_desc;
+ ipcoa.sec_qos = oa->sec_qos;
+
+ status = __ntapi->zw_open_symbolic_link_object(
+ &hsymlink,
+ NT_SEC_STANDARD_RIGHTS_READ | NT_GENERIC_READ,
+ &ipcoa);
+
+ switch (status) {
+ case NT_STATUS_SUCCESS:
+ break;
+
+ case NT_STATUS_OBJECT_NAME_NOT_FOUND:
+ case NT_STATUS_OBJECT_PATH_NOT_FOUND:
+ if (oa->obj_attr & NT_OBJ_OPENIF)
+ return __msq_open(
+ hport,msq,access,
+ oa,iosb,share,nslots,
+ key,0,NT_TTY_MSQ_ALLOC);
+ else
+ return status;
+
+ default:
+ return status;
+ }
+
+ /* msqctl service attributes */
+ if (!rtdata->hmsqpid)
+ if ((status = __msqctl_get_service_attr(rtdata,&msqctl)))
+ return status;
+
+ /* msqctl server */
+ if ((status = __msqctl_server_connect(rtdata,&msqctl)))
+ return status;
+
+ /* msqpid symlink */
+ if ((status = __msqpid_symlink_set(rtdata,&msqctl)))
+ return status;
+
+ /* ipc connect */
+ status = __ntapi->ipc_connect_by_symlink(
+ &hipc,hsymlink);
+
+ __ntapi->zw_close(
+ hsymlink);
+
+ if (status)
+ return status;
+
+ /* open by id? */
+ if (oa->obj_attr & NT_OBJ_OPENLINK) {
+ id = key;
+ key = 0;
+ } else {
+ id = 0;
+ }
+
+ return __msq_open(
+ hipc,msq,access,
+ oa,iosb,share,nslots,
+ key,id,NT_TTY_MSQ_OPEN);
+}