summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authormidipix <writeonce@midipix.org>2017-07-30 21:21:21 +0000
committermidipix <writeonce@midipix.org>2017-07-31 08:43:36 -0400
commit9faf9a067cfeaa786ac1784fb8bf4eece49922e9 (patch)
tree46950830693387fa1223c43445b1f1c022408c80 /src
parent029ed17d66b232d5e8bea0b3ab543ec8331e563d (diff)
downloadntapi-9faf9a067cfeaa786ac1784fb8bf4eece49922e9.tar.bz2
ntapi-9faf9a067cfeaa786ac1784fb8bf4eece49922e9.tar.xz
subsystem interfaces: integrated sysv semaphore client-side interfaces.
Diffstat (limited to 'src')
-rw-r--r--src/internal/ntapi.c10
-rw-r--r--src/internal/ntapi_fnapi.h10
-rw-r--r--src/sem/ntapi_sem_connect.c335
-rw-r--r--src/sem/ntapi_sem_fcntl.c41
-rw-r--r--src/sem/ntapi_sem_fdio.c65
-rw-r--r--src/sem/ntapi_sem_ioctl.c115
-rw-r--r--src/sem/ntapi_sem_query.c130
-rw-r--r--src/sem/ntapi_sem_set.c117
8 files changed, 823 insertions, 0 deletions
diff --git a/src/internal/ntapi.c b/src/internal/ntapi.c
index 42812c0..2459534 100644
--- a/src/internal/ntapi.c
+++ b/src/internal/ntapi.c
@@ -191,6 +191,16 @@ static int32_t __fastcall __ntapi_init_once(ntapi_vtbl ** pvtbl)
__ntapi->ipc_init_section_by_port = __ntapi_ipc_init_section_by_port;
__ntapi->ipc_disconnect_unmap_section_by_port = __ntapi_ipc_disconnect_unmap_section_by_port;
+ /* nt_sem.h */
+ __ntapi->sem_create = __ntapi_sem_create;
+ __ntapi->sem_open = __ntapi_sem_open;
+ __ntapi->sem_fcntl = __ntapi_sem_fcntl;
+ __ntapi->sem_ioctl = __ntapi_sem_ioctl;
+ __ntapi->sem_query = __ntapi_sem_query;
+ __ntapi->sem_set = __ntapi_sem_set;
+ __ntapi->sem_cancel = __ntapi_sem_cancel;
+ __ntapi->sem_free = __ntapi_sem_free;
+
/* nt_ldr.h */
__ntapi->ldr_load_system_dll = __ntapi_ldr_load_system_dll;
__ntapi->ldr_create_state_snapshot = __ntapi_ldr_create_state_snapshot;
diff --git a/src/internal/ntapi_fnapi.h b/src/internal/ntapi_fnapi.h
index 39f8ac3..e7cb5ae 100644
--- a/src/internal/ntapi_fnapi.h
+++ b/src/internal/ntapi_fnapi.h
@@ -59,6 +59,16 @@ ntapi_ipc_disconnect_unmap_section_by_port __ntapi_ipc_disconnect_unmap_section_
ntapi_ipc_create_pipe __ntapi_ipc_create_pipe_v1;
ntapi_ipc_create_pipe __ntapi_ipc_create_pipe_v2;
+/* nt_sem.h */
+ntapi_sem_create __ntapi_sem_create;
+ntapi_sem_open __ntapi_sem_open;
+ntapi_sem_fcntl __ntapi_sem_fcntl;
+ntapi_sem_ioctl __ntapi_sem_ioctl;
+ntapi_sem_query __ntapi_sem_query;
+ntapi_sem_set __ntapi_sem_set;
+ntapi_sem_cancel __ntapi_sem_cancel;
+ntapi_sem_free __ntapi_sem_free;
+
/* nt_ldr */
ntapi_ldr_load_system_dll __ntapi_ldr_load_system_dll;
ntapi_ldr_create_state_snapshot __ntapi_ldr_create_state_snapshot;
diff --git a/src/sem/ntapi_sem_connect.c b/src/sem/ntapi_sem_connect.c
new file mode 100644
index 0000000..32c3610
--- /dev/null
+++ b/src/sem/ntapi_sem_connect.c
@@ -0,0 +1,335 @@
+/********************************************************/
+/* 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_sem.h>
+#include <ntapi/ntapi.h>
+#include "ntapi_impl.h"
+
+static const nt_guid g_sempid = NT_IPC_GUID_SEMPID;
+static const wchar16_t p_sempid[6] = NT_IPC_OBJDIR_PREFIX_SEMPID;
+
+static int32_t __semctl_get_service_attr(
+ nt_rtdata * rtdata,
+ nt_tty_service_info * semctl)
+{
+ nt_iosb iosb;
+
+ /* inherited runtime data? */
+ if (rtdata->semctl_keys[0]) {
+ semctl->attr.ver_major = 0;
+ semctl->attr.ver_minor = 0;
+ semctl->attr.options = 0;
+ semctl->attr.flags = 0;
+
+ semctl->attr.type = rtdata->semctl_type;
+ semctl->attr.subtype = rtdata->semctl_subtype;
+
+ semctl->attr.keys.key[0] = rtdata->semctl_keys[0];
+ semctl->attr.keys.key[1] = rtdata->semctl_keys[1];
+ semctl->attr.keys.key[2] = rtdata->semctl_keys[2];
+ semctl->attr.keys.key[3] = rtdata->semctl_keys[3];
+ semctl->attr.keys.key[4] = rtdata->semctl_keys[4];
+ semctl->attr.keys.key[5] = rtdata->semctl_keys[5];
+
+ __ntapi->tt_guid_copy(
+ &semctl->attr.guid,
+ &rtdata->semctl_guid);
+
+ return NT_STATUS_SUCCESS;
+ }
+
+ /* obtain service info */
+ return __ntapi->tty_query_information_service(
+ 0,&iosb,
+ semctl,&(nt_guid)NT_PORT_GUID_SEMCTL,
+ 0,0);
+}
+
+static int32_t __semctl_server_connect(
+ nt_rtdata * rtdata,
+ nt_tty_service_info * semctl)
+{
+ int32_t status;
+
+ /* already cononected? */
+ if (rtdata->hsemctl)
+ return NT_STATUS_SUCCESS;
+
+ /* connect */
+ if ((status = __ntapi->ipc_connect_by_attr(
+ &rtdata->hsemctl,
+ &semctl->attr)))
+ return status;
+
+ /* update */
+ rtdata->semctl_type = semctl->attr.type;
+ rtdata->semctl_subtype = semctl->attr.subtype;
+
+ rtdata->semctl_keys[0] = semctl->attr.keys.key[0];
+ rtdata->semctl_keys[1] = semctl->attr.keys.key[1];
+ rtdata->semctl_keys[2] = semctl->attr.keys.key[2];
+ rtdata->semctl_keys[3] = semctl->attr.keys.key[3];
+ rtdata->semctl_keys[4] = semctl->attr.keys.key[4];
+ rtdata->semctl_keys[5] = semctl->attr.keys.key[5];
+
+ __ntapi->tt_guid_copy(
+ &rtdata->semctl_guid,
+ &semctl->attr.guid);
+
+ return NT_STATUS_SUCCESS;
+}
+
+static int32_t __sempid_symlink_set(
+ nt_rtdata * rtdata,
+ nt_tty_service_info * semctl)
+{
+ int32_t status;
+ void * hpiddir;
+ nt_port_name svcname;
+ nt_unicode_string str;
+
+ if (rtdata->hsempid)
+ return NT_STATUS_SUCCESS;
+
+ if (!rtdata->hsempiddir) {
+ if ((status = __ntapi->tt_open_ipc_object_directory(
+ &hpiddir,
+ NT_DIRECTORY_ALL_ACCESS,
+ p_sempid,&g_sempid)))
+ return status;
+
+ if (at_locked_cas((intptr_t *)&rtdata->hsempiddir,0,(intptr_t)hpiddir))
+ __ntapi->zw_close(hpiddir);
+ }
+
+ __ntapi->tt_port_name_from_attr(
+ &svcname,&semctl->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->hsempid,
+ NT_SEC_STANDARD_RIGHTS_ALL,
+ rtdata->hsempiddir,
+ 0,&str,
+ pe_get_current_process_id());
+
+}
+
+static int32_t __stdcall __sem_open(
+ void * hipc,
+ nt_sem_info * sem,
+ uint32_t access,
+ nt_object_attributes * oa,
+ nt_iosb * iosb,
+ uint32_t share,
+ uint32_t semslots,
+ uint32_t key,
+ uint32_t id,
+ uint32_t opcode)
+{
+ int32_t status;
+ nt_tty_port_msg msg;
+ nt_iosb siosb;
+ nt_tty_service_info semctl;
+ nt_runtime_data * rtdata;
+
+ /* init */
+ rtdata = (__ntapi_internals())->rtdata;
+
+ /* semctl service attributes */
+ if (!rtdata->hsempid)
+ if ((status = __semctl_get_service_attr(rtdata,&semctl)))
+ return status;
+
+ /* semctl server */
+ if ((status = __semctl_server_connect(rtdata,&semctl)))
+ return status;
+
+ /* sempid symlink */
+ if ((status = __sempid_symlink_set(rtdata,&semctl)))
+ return status;
+
+ /* hipc */
+ if (!hipc && (opcode == NT_TTY_SEM_ALLOC))
+ hipc = (__ntapi_internals())->rtdata->hsemctl;
+
+ /* obtain sem 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_sem_info_msg) - sizeof(msg.header);
+ msg.header.msg_size = sizeof(msg);
+ msg.ttyinfo.opcode = opcode;
+
+ msg.seminfo.semkey = (int32_t)key;
+ msg.seminfo.semid = (int32_t)id;
+ msg.seminfo.semslots = semslots;
+
+ msg.seminfo.ntattr = oa->obj_attr;
+ msg.seminfo.ntaccess = access;
+ msg.seminfo.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 semaphore? */
+ if (opcode == NT_TTY_SEM_ALLOC)
+ if ((status = __ntapi->ipc_connect_by_attr(
+ &hipc,&msg.svcinfo.attr)))
+ return status;
+
+ /* all done */
+ __ntapi->tt_aligned_block_memset(
+ (uintptr_t *)sem,
+ 0,sizeof(*sem));
+
+ sem->semkey = msg.svcinfo.key;
+ sem->semid = msg.svcinfo.id;
+
+ sem->hport = hipc;
+
+ return NT_STATUS_SUCCESS;
+}
+
+
+int32_t __ntapi_sem_create(
+ __in void * hport,
+ __out nt_sem_info * sem,
+ __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 semaphore */
+ return __sem_open(
+ hport,sem,access,
+ oa,iosb,share,nslots,
+ key,0,NT_TTY_SEM_ALLOC);
+}
+
+
+int32_t __stdcall __ntapi_sem_open(
+ __in void * hport,
+ __out nt_sem_info * sem,
+ __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;
+
+ /* 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 __sem_open(
+ hport,sem,access,
+ oa,iosb,share,nslots,
+ key,0,NT_TTY_SEM_ALLOC);
+ else
+ return status;
+
+ default:
+ 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 __sem_open(
+ hipc,sem,access,
+ oa,iosb,share,nslots,
+ key,id,NT_TTY_SEM_OPEN);
+}
diff --git a/src/sem/ntapi_sem_fcntl.c b/src/sem/ntapi_sem_fcntl.c
new file mode 100644
index 0000000..d48557f
--- /dev/null
+++ b/src/sem/ntapi_sem_fcntl.c
@@ -0,0 +1,41 @@
+/********************************************************/
+/* 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_sem.h>
+#include <ntapi/ntapi.h>
+#include "ntapi_impl.h"
+
+int32_t __stdcall __ntapi_sem_fcntl(
+ __in nt_sem_info * sem,
+ __in void * hevent __optional,
+ __in nt_io_apc_routine * apc_routine __optional,
+ __in void * apc_context __optional,
+ __out nt_iosb * iosb,
+ __in uint32_t fs_control_code,
+ __in void * input_buffer __optional,
+ __in uint32_t input_buffer_length,
+ __out void * output_buffer __optional,
+ __in uint32_t output_buffer_length)
+{
+ (void)sem;
+ (void)hevent;
+ (void)apc_routine;
+ (void)apc_context;
+ (void)iosb;
+ (void)fs_control_code;
+ (void)input_buffer;
+ (void)input_buffer_length;
+ (void)output_buffer;
+ (void)output_buffer_length;
+
+ return 0;
+}
diff --git a/src/sem/ntapi_sem_fdio.c b/src/sem/ntapi_sem_fdio.c
new file mode 100644
index 0000000..5840226
--- /dev/null
+++ b/src/sem/ntapi_sem_fdio.c
@@ -0,0 +1,65 @@
+/********************************************************/
+/* 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_sem.h>
+#include <ntapi/ntapi.h>
+#include "ntapi_impl.h"
+
+static int32_t __sem_fdio(
+ nt_sem_info * sem,
+ nt_iosb * iosb,
+ uint32_t opcode)
+{
+ int32_t status;
+ nt_sem_info_msg msg;
+
+ /* validate */
+ if (!iosb)
+ return NT_STATUS_INVALID_PARAMETER;
+
+ /* msg */
+ __ntapi->tt_aligned_block_memset(
+ &msg,0,sizeof(msg));
+
+ msg.header.msg_type = NT_LPC_NEW_MESSAGE;
+ msg.header.data_size = sizeof(msg.data);
+ msg.header.msg_size = sizeof(msg);
+ msg.data.ttyinfo.opcode = opcode;
+
+ msg.data.seminfo.semkey = sem->semkey;
+ msg.data.seminfo.semid = sem->semid;
+ msg.data.seminfo.sempid = sem->sempid;
+
+ if ((status = __ntapi->zw_request_wait_reply_port(sem->hport,&msg,&msg)))
+ return status;
+ else if (msg.data.ttyinfo.status)
+ return msg.data.ttyinfo.status;
+
+ iosb->status = NT_STATUS_SUCCESS;
+ iosb->info = 0;
+
+ return NT_STATUS_SUCCESS;
+}
+
+int32_t __stdcall __ntapi_sem_cancel(
+ __in nt_sem_info * sem,
+ __out nt_iosb * iosb)
+{
+ return __sem_fdio(sem,iosb,NT_TTY_SEM_CANCEL);
+}
+
+int32_t __stdcall __ntapi_sem_free(
+ __in nt_sem_info * sem,
+ __out nt_iosb * iosb)
+{
+ return __sem_fdio(sem,iosb,NT_TTY_SEM_FREE);
+}
diff --git a/src/sem/ntapi_sem_ioctl.c b/src/sem/ntapi_sem_ioctl.c
new file mode 100644
index 0000000..2e7ac37
--- /dev/null
+++ b/src/sem/ntapi_sem_ioctl.c
@@ -0,0 +1,115 @@
+/********************************************************/
+/* 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_sem.h>
+#include <ntapi/ntapi.h>
+#include "ntapi_impl.h"
+
+static int32_t __sem_ioctl_return(
+ intptr_t * hlock,
+ int32_t status)
+{
+ at_store(hlock,0);
+ return status;
+}
+
+
+int32_t __stdcall __ntapi_sem_ioctl(
+ __in nt_sem_info * sem,
+ __in void * hevent __optional,
+ __in nt_io_apc_routine * apc_routine __optional,
+ __in void * apc_context __optional,
+ __out nt_iosb * iosb,
+ __in uint32_t io_control_code,
+ __in void * input_buffer __optional,
+ __in uint32_t input_buffer_length,
+ __out void * output_buffer __optional,
+ __in uint32_t output_buffer_length)
+{
+ int32_t status;
+ void * hsection;
+ void * secaddr;
+ size_t secsize;
+ nt_sem_info_msg msg;
+ intptr_t * hlock;
+
+ (void)output_buffer;
+ (void)output_buffer_length;
+
+ /* validate */
+ if (io_control_code)
+ return NT_STATUS_NOT_SUPPORTED;
+
+ else if (!iosb)
+ return NT_STATUS_INVALID_PARAMETER;
+
+ else if (!input_buffer_length)
+ return NT_STATUS_INVALID_PARAMETER;
+
+ else if (input_buffer_length % sizeof(nt_sem_op))
+ return NT_STATUS_INFO_LENGTH_MISMATCH;
+
+ /* section */
+ if (sem->section_addr) {
+ hsection = sem->section;
+ secaddr = sem->section_addr;
+ secsize = sem->section_size;
+
+ } else if ((status = __ntapi->ipc_init_section_by_port(
+ sem->hport,&hsection,
+ &secaddr,&secsize)))
+ return status;
+
+ if (input_buffer_length > secsize)
+ return NT_STATUS_INFO_LENGTH_MISMATCH;
+
+ /* lock */
+ hlock = &(__ntapi_internals()->hlock);
+
+ if (at_locked_cas(hlock,0,1))
+ return NT_STATUS_RESOURCE_NOT_OWNED;
+
+ /* semop array to section */
+ __ntapi->tt_generic_memcpy(
+ secaddr,input_buffer,
+ input_buffer_length);
+
+ /* msg */
+ __ntapi->tt_aligned_block_memset(
+ &msg,0,sizeof(msg));
+
+ msg.header.msg_type = NT_LPC_NEW_MESSAGE;
+ msg.header.data_size = sizeof(msg.data);
+ msg.header.msg_size = sizeof(msg);
+ msg.data.ttyinfo.opcode = NT_TTY_SEM_IOCTL;
+
+ msg.data.seminfo.semkey = sem->semkey;
+ msg.data.seminfo.semid = sem->semid;
+ msg.data.seminfo.sempid = sem->sempid;
+ msg.data.seminfo.section_addr = secaddr;
+ msg.data.seminfo.section_size = input_buffer_length;
+
+ msg.data.seminfo.hevent[0] = hevent;
+ msg.data.seminfo.apc_routine = apc_routine;
+ msg.data.seminfo.apc_context = apc_context;
+ msg.data.seminfo.riosb = iosb;
+
+ if ((status = __ntapi->zw_request_wait_reply_port(sem->hport,&msg,&msg)))
+ return __sem_ioctl_return(hlock,status);
+ else if (msg.data.ttyinfo.status)
+ return __sem_ioctl_return(hlock,msg.data.ttyinfo.status);
+
+ iosb->status = NT_STATUS_SUCCESS;
+ iosb->info = 0;
+
+ return __sem_ioctl_return(hlock,NT_STATUS_SUCCESS);
+}
diff --git a/src/sem/ntapi_sem_query.c b/src/sem/ntapi_sem_query.c
new file mode 100644
index 0000000..816d50d
--- /dev/null
+++ b/src/sem/ntapi_sem_query.c
@@ -0,0 +1,130 @@
+/********************************************************/
+/* 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_sem.h>
+#include <ntapi/ntapi.h>
+#include "ntapi_impl.h"
+
+static int32_t __sem_query_return(
+ intptr_t * hlock,
+ int32_t status,
+ int32_t cmd)
+{
+ if (cmd == NT_SEM_CMD_GETALL)
+ at_store(hlock,0);
+
+ return status;
+}
+
+int32_t __stdcall __ntapi_sem_query(
+ __in nt_sem_info * sem,
+ __out nt_io_status_block * iosb,
+ __out void * sem_info,
+ __in uint32_t sem_info_length,
+ __in int32_t sem_ipc_cmd)
+{
+ int32_t status;
+ void * hsection;
+ void * secaddr;
+ size_t secsize;
+ nt_sem_info_msg msg;
+ intptr_t * hlock;
+
+ /* validate */
+ if (!iosb)
+ return NT_STATUS_INVALID_PARAMETER;
+
+ else if (!sem_info)
+ return NT_STATUS_INVALID_PARAMETER;
+
+ else if (!sem_info_length)
+ return NT_STATUS_INVALID_PARAMETER;
+
+ else if (sem_ipc_cmd != NT_SEM_CMD_GETALL)
+ if (sem_info_length != sizeof(nt_sem_info))
+ return NT_STATUS_INFO_LENGTH_MISMATCH;
+
+ /* section */
+ hsection = 0;
+ secaddr = 0;
+ secsize = 0;
+
+ if (sem_ipc_cmd == NT_SEM_CMD_GETALL) {
+ if (sem->section_addr) {
+ hsection = sem->section;
+ secaddr = sem->section_addr;
+ secsize = sem->section_size;
+
+ } else if ((status = __ntapi->ipc_init_section_by_port(
+ sem->hport,&hsection,
+ &secaddr,&secsize)))
+ return status;
+
+ /* lock */
+ hlock = &(__ntapi_internals()->hlock);
+
+ if (at_locked_cas(hlock,0,1))
+ return NT_STATUS_RESOURCE_NOT_OWNED;
+ }
+
+ /* msg */
+ __ntapi->tt_aligned_block_memset(
+ &msg,0,sizeof(msg));
+
+ msg.header.msg_type = NT_LPC_NEW_MESSAGE;
+ msg.header.data_size = sizeof(msg.data);
+ msg.header.msg_size = sizeof(msg);
+ msg.data.ttyinfo.opcode = NT_TTY_SEM_QUERY;
+
+ msg.data.seminfo.semcmd = sem_ipc_cmd;
+ msg.data.seminfo.semkey = sem->semkey;
+ msg.data.seminfo.semid = sem->semid;
+ msg.data.seminfo.semnum = sem->semnum;
+ msg.data.seminfo.section_addr = secaddr;
+ msg.data.seminfo.section_size = secsize;
+
+ if ((status = __ntapi->zw_request_wait_reply_port(sem->hport,&msg,&msg)))
+ return __sem_query_return(hlock,status,sem_ipc_cmd);
+ else if (msg.data.ttyinfo.status)
+ return __sem_query_return(hlock,msg.data.ttyinfo.status,sem_ipc_cmd);
+
+ /* reply */
+ if (sem_ipc_cmd == NT_SEM_CMD_GETALL) {
+ if (msg.data.seminfo.section_size > sem_info_length)
+ return __sem_query_return(
+ hlock,
+ NT_STATUS_BUFFER_TOO_SMALL,
+ sem_ipc_cmd);
+
+ __ntapi->tt_generic_memcpy(
+ sem_info,secaddr,
+ msg.data.seminfo.section_size);
+
+ at_store(hlock,0);
+
+ iosb->status = NT_STATUS_SUCCESS;
+ iosb->info = msg.data.seminfo.section_size;
+ } else {
+ if (msg.header.data_size != sizeof(msg.data))
+ return NT_STATUS_UNEXPECTED_IO_ERROR;
+
+ __ntapi->tt_generic_memcpy(
+ sem_info,
+ &msg.data.seminfo,
+ sizeof(msg.data.seminfo));
+
+ iosb->status = NT_STATUS_SUCCESS;
+ iosb->info = sizeof(msg.data.seminfo);
+ }
+
+ return NT_STATUS_SUCCESS;
+}
diff --git a/src/sem/ntapi_sem_set.c b/src/sem/ntapi_sem_set.c
new file mode 100644
index 0000000..813de30
--- /dev/null
+++ b/src/sem/ntapi_sem_set.c
@@ -0,0 +1,117 @@
+/********************************************************/
+/* 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_sem.h>
+#include <ntapi/ntapi.h>
+#include "ntapi_impl.h"
+
+static int32_t __sem_set_return(
+ intptr_t * hlock,
+ int32_t status,
+ int32_t cmd)
+{
+ if (cmd == NT_SEM_CMD_SETALL)
+ at_store(hlock,0);
+
+ return status;
+}
+
+int32_t __stdcall __ntapi_sem_set(
+ __in nt_sem_info * sem,
+ __out nt_io_status_block * iosb,
+ __in void * sem_info,
+ __in uint32_t sem_info_length,
+ __in int32_t sem_ipc_cmd)
+{
+ int32_t status;
+ void * hsection;
+ void * secaddr;
+ size_t secsize;
+ nt_sem_info_msg msg;
+ intptr_t * hlock;
+
+ /* validate */
+ if (!iosb)
+ return NT_STATUS_INVALID_PARAMETER;
+
+ else if (!sem_info)
+ return NT_STATUS_INVALID_PARAMETER;
+
+ else if (!sem_info_length)
+ return NT_STATUS_INVALID_PARAMETER;
+
+ else if (sem_ipc_cmd != NT_SEM_CMD_SETALL)
+ if (sem_info_length != sizeof(nt_sem_info))
+ return NT_STATUS_INFO_LENGTH_MISMATCH;
+
+ /* section */
+ hsection = 0;
+ secaddr = 0;
+ secsize = 0;
+
+ /* SETALL */
+ if (sem_ipc_cmd == NT_SEM_CMD_SETALL) {
+ if (sem->section_addr) {
+ hsection = sem->section;
+ secaddr = sem->section_addr;
+ secsize = sem->section_size;
+
+ } else if ((status = __ntapi->ipc_init_section_by_port(
+ sem->hport,&hsection,
+ &secaddr,&secsize)))
+ return status;
+
+ /* data size */
+ if (secsize < sem_info_length)
+ return NT_STATUS_DATA_OVERRUN;
+
+ /* lock */
+ hlock = &(__ntapi_internals()->hlock);
+
+ if (at_locked_cas(hlock,0,1))
+ return NT_STATUS_RESOURCE_NOT_OWNED;
+
+ /* data copy */
+ __ntapi->tt_generic_memcpy(
+ secaddr,sem_info,
+ sem_info_length);
+ } else
+ hlock = 0;
+
+ /* msg */
+ __ntapi->tt_aligned_block_memset(
+ &msg,0,sizeof(msg));
+
+ msg.header.msg_type = NT_LPC_NEW_MESSAGE;
+ msg.header.data_size = sizeof(msg.data);
+ msg.header.msg_size = sizeof(msg);
+ msg.data.ttyinfo.opcode = NT_TTY_SEM_SET;
+
+ msg.data.seminfo.semcmd = sem_ipc_cmd;
+ msg.data.seminfo.semkey = sem->semkey;
+ msg.data.seminfo.semid = sem->semid;
+ msg.data.seminfo.semnum = sem->semnum;
+ msg.data.seminfo.semval = sem->semval;
+ msg.data.seminfo.section_addr = secaddr;
+ msg.data.seminfo.section_size = sem_info_length;
+
+ if ((status = __ntapi->zw_request_wait_reply_port(sem->hport,&msg,&msg)))
+ return __sem_set_return(hlock,status,sem_ipc_cmd);
+ else if (msg.data.ttyinfo.status)
+ return __sem_set_return(hlock,msg.data.ttyinfo.status,sem_ipc_cmd);
+
+ /* reply */
+ iosb->status = NT_STATUS_SUCCESS;
+ iosb->info = 0;
+
+ return __sem_set_return(hlock,NT_STATUS_SUCCESS,sem_ipc_cmd);
+}