summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authormidipix <writeonce@midipix.org>2017-08-04 22:22:22 +0000
committermidipix <writeonce@midipix.org>2017-08-04 17:33:16 -0400
commitedb08567093daae164f6d3955884117dee74fe98 (patch)
treea0cbce284eccf262c4a2c65289b373658af59189
parent335494754eba35020cb2d4fd8c976fdb3a6e3507 (diff)
downloadntapi-edb08567093daae164f6d3955884117dee74fe98.tar.bz2
ntapi-edb08567093daae164f6d3955884117dee74fe98.tar.xz
subsystem interfaces: added server-to-server synchronization interfaces.
-rw-r--r--include/ntapi/nt_ipc.h13
-rw-r--r--include/ntapi/nt_process.h6
-rw-r--r--include/ntapi/nt_tty.h73
-rw-r--r--include/ntapi/ntapi.h2
-rw-r--r--src/internal/ntapi.c2
-rw-r--r--src/internal/ntapi_fnapi.h2
-rw-r--r--src/ipc/ntapi_ipc_connect.c212
-rw-r--r--src/process/ntapi_tt_fork.c12
-rw-r--r--src/sem/ntapi_sem_connect.c30
-rw-r--r--src/sem/ntapi_sem_fcntl.c3
10 files changed, 341 insertions, 14 deletions
diff --git a/include/ntapi/nt_ipc.h b/include/ntapi/nt_ipc.h
index 7238146..80760c1 100644
--- a/include/ntapi/nt_ipc.h
+++ b/include/ntapi/nt_ipc.h
@@ -85,6 +85,19 @@ typedef int32_t __stdcall ntapi_ipc_connect_section_by_port(
__out size_t * section_size);
+typedef int32_t __stdcall ntapi_ipc_get_port_by_attr(
+ __out void ** hport,
+ __in nt_port_attr * attr);
+
+
+typedef int32_t __stdcall ntapi_ipc_get_port_section_by_attr(
+ __out void ** hport,
+ __in nt_port_attr * attr,
+ __out void ** hsection,
+ __out void ** section_addr,
+ __out size_t * section_size);
+
+
typedef int32_t __stdcall ntapi_ipc_init_section_by_port(
__in void * hconn,
__out void ** hsection,
diff --git a/include/ntapi/nt_process.h b/include/ntapi/nt_process.h
index 96bc727..c284185 100644
--- a/include/ntapi/nt_process.h
+++ b/include/ntapi/nt_process.h
@@ -60,6 +60,8 @@ typedef enum _nt_process_opcode_idx {
NT_PROCESS_OPCODE_IDX_EXECVE,
NT_PROCESS_OPCODE_IDX_STOPPED,
NT_PROCESS_OPCODE_IDX_CONTINUED,
+ NT_PROCESS_OPCODE_IDX_CLIENT,
+ NT_PROCESS_OPCODE_IDX_SERVER,
} nt_process_opcode_idx;
@@ -505,6 +507,10 @@ typedef struct _nt_runtime_data {
int32_t ppid_type;
int32_t ppid_subtype;
uint32_t ppid_keys[6];
+ nt_guid ipc_guid;
+ int32_t ipc_type;
+ int32_t ipc_subtype;
+ uint32_t ipc_keys[6];
nt_guid semctl_guid;
int32_t semctl_type;
int32_t semctl_subtype;
diff --git a/include/ntapi/nt_tty.h b/include/ntapi/nt_tty.h
index 387c8b6..5555d85 100644
--- a/include/ntapi/nt_tty.h
+++ b/include/ntapi/nt_tty.h
@@ -50,6 +50,9 @@ typedef enum _nt_tty_opcode {
NT_TTY_CLIENT_SESSION_DISCONNECT,
NT_TTY_CLIENT_SESSION_QUERY,
NT_TTY_CLIENT_SESSION_SET,
+ /* server-to-server coordination */
+ NT_TTY_CLIENT_SESSION_SYNCHRONIZE,
+ NT_TTY_CLIENT_SESSION_TRANSFER,
/* process registration */
NT_TTY_CLIENT_PROCESS_REGISTER,
NT_TTY_CLIENT_PROCESS_UNREGISTER,
@@ -87,6 +90,8 @@ typedef enum _nt_tty_opcode {
NT_TTY_SEM_IOCTL,
NT_TTY_SEM_CANCEL,
NT_TTY_SEM_TRACE,
+ NT_TTY_SEM_TRANSFER,
+ NT_TTY_SEM_WAIT,
/* virtual mount system */
NT_TTY_VMS_QUERY,
NT_TTY_VMS_REQUEST,
@@ -271,6 +276,40 @@ typedef struct __attr_ptr_size_aligned__ _nt_tty_session_info {
int32_t syspid;
} nt_tty_session_info;
+
+typedef struct __attr_ptr_size_aligned__ _nt_tty_ipc_info {
+ nt_port_attr ctrlsvc;
+ uint32_t ipckeys[6];
+ void * hevent;
+ void * apc_routine;
+ void * apc_context;
+ nt_iosb * riosb;
+} nt_tty_ipc_info;
+
+
+typedef struct __attr_ptr_size_aligned__ _nt_tty_sync_info {
+ nt_client_id cid;
+ nt_port_attr ipcsvc;
+ uint32_t ipckeys[6];
+ void * hevent;
+ void * apc_routine;
+ void * apc_context;
+ nt_iosb * riosb;
+} nt_tty_sync_info;
+
+
+
+typedef struct __attr_ptr_size_aligned__ _nt_tty_transfer_info {
+ nt_client_id ccid;
+ nt_client_id tcid;
+ uint32_t ipckeys[6];
+ void * hevent;
+ void * apc_routine;
+ void * apc_context;
+ nt_iosb * riosb;
+} nt_tty_transfer_info;
+
+
typedef struct __attr_ptr_size_aligned__ _nt_tty_register_msg {
nt_port_message header;
struct {
@@ -334,6 +373,33 @@ typedef struct __attr_ptr_size_aligned__ _nt_tty_pid_msg {
} nt_tty_pid_msg;
+typedef struct __attr_ptr_size_aligned__ _nt_tty_ipc_msg {
+ nt_port_message header;
+ struct {
+ nt_tty_msg_info ttyinfo;
+ nt_tty_ipc_info ipcinfo;
+ } data;
+} nt_tty_ipc_msg;
+
+
+typedef struct __attr_ptr_size_aligned__ _nt_tty_sync_msg {
+ nt_port_message header;
+ struct {
+ nt_tty_msg_info ttyinfo;
+ nt_tty_sync_info syncinfo;
+ } data;
+} nt_tty_sync_msg;
+
+
+typedef struct __attr_ptr_size_aligned__ _nt_tty_transfer_msg {
+ nt_port_message header;
+ struct {
+ nt_tty_msg_info ttyinfo;
+ nt_tty_transfer_info transferinfo;
+ } data;
+} nt_tty_transfer_msg;
+
+
typedef struct __attr_ptr_size_aligned__ _nt_pty_fd_msg {
nt_port_message header;
struct {
@@ -387,6 +453,10 @@ typedef struct __attr_ptr_size_aligned__ _nt_tty_port_msg {
nt_tty_vms_info vmsinfo;
nt_tty_peer_info peerinfo;
nt_tty_sigctl_info ctlinfo;
+ nt_tty_ipc_info ipcinfo;
+ nt_tty_sync_info syncinfo;
+ nt_user_process_info pidinfo;
+ nt_tty_transfer_info transferinfo;
nt_pty_fd_info fdinfo;
nt_pty_io_info ioinfo;
nt_pty_client_info clientinfo;
@@ -412,6 +482,9 @@ __assert_aligned_size(nt_pty_sigctl_msg, __SIZEOF_POINTER__);
__assert_aligned_size(nt_pty_fd_msg, __SIZEOF_POINTER__);
__assert_aligned_size(nt_pty_io_msg, __SIZEOF_POINTER__);
__assert_aligned_size(nt_tty_port_msg, __SIZEOF_POINTER__);
+__assert_aligned_size(nt_tty_ipc_msg, __SIZEOF_POINTER__);
+__assert_aligned_size(nt_tty_sync_msg, __SIZEOF_POINTER__);
+__assert_aligned_size(nt_tty_transfer_msg, __SIZEOF_POINTER__);
/* tty session */
diff --git a/include/ntapi/ntapi.h b/include/ntapi/ntapi.h
index 23a99aa..71416d8 100644
--- a/include/ntapi/ntapi.h
+++ b/include/ntapi/ntapi.h
@@ -397,6 +397,8 @@ typedef struct _ntapi_vtbl {
ntapi_ipc_connect_section_by_name * ipc_connect_section_by_name;
ntapi_ipc_connect_section_by_symlink * ipc_connect_section_by_symlink;
ntapi_ipc_connect_section_by_port * ipc_connect_section_by_port;
+ ntapi_ipc_get_port_by_attr * ipc_get_port_by_attr;
+ ntapi_ipc_get_port_section_by_attr * ipc_get_port_section_by_attr;
ntapi_ipc_init_section_by_port * ipc_init_section_by_port;
ntapi_ipc_disconnect_unmap_section_by_port * ipc_disconnect_unmap_section_by_port;
ntapi_ipc_create_pipe * ipc_create_pipe;
diff --git a/src/internal/ntapi.c b/src/internal/ntapi.c
index 2459534..0940ebd 100644
--- a/src/internal/ntapi.c
+++ b/src/internal/ntapi.c
@@ -188,6 +188,8 @@ static int32_t __fastcall __ntapi_init_once(ntapi_vtbl ** pvtbl)
__ntapi->ipc_connect_section_by_name = __ntapi_ipc_connect_section_by_name;
__ntapi->ipc_connect_section_by_symlink = __ntapi_ipc_connect_section_by_symlink;
__ntapi->ipc_connect_section_by_port = __ntapi_ipc_connect_section_by_port;
+ __ntapi->ipc_get_port_by_attr = __ntapi_ipc_get_port_by_attr;
+ __ntapi->ipc_get_port_section_by_attr = __ntapi_ipc_get_port_section_by_attr;
__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;
diff --git a/src/internal/ntapi_fnapi.h b/src/internal/ntapi_fnapi.h
index e7cb5ae..1e770ce 100644
--- a/src/internal/ntapi_fnapi.h
+++ b/src/internal/ntapi_fnapi.h
@@ -54,6 +54,8 @@ ntapi_ipc_connect_section_by_attr __ntapi_ipc_connect_section_by_attr;
ntapi_ipc_connect_section_by_name __ntapi_ipc_connect_section_by_name;
ntapi_ipc_connect_section_by_symlink __ntapi_ipc_connect_section_by_symlink;
ntapi_ipc_connect_section_by_port __ntapi_ipc_connect_section_by_port;
+ntapi_ipc_get_port_by_attr __ntapi_ipc_get_port_by_attr;
+ntapi_ipc_get_port_section_by_attr __ntapi_ipc_get_port_section_by_attr;
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;
ntapi_ipc_create_pipe __ntapi_ipc_create_pipe_v1;
diff --git a/src/ipc/ntapi_ipc_connect.c b/src/ipc/ntapi_ipc_connect.c
index fceb527..6584f49 100644
--- a/src/ipc/ntapi_ipc_connect.c
+++ b/src/ipc/ntapi_ipc_connect.c
@@ -20,14 +20,142 @@ static int32_t __ipc_connect_return(
}
+static void __ipc_init_ctrl_msg_semctl(
+ const nt_port_attr * attr,
+ nt_tty_ipc_msg * msg)
+{
+ __ntapi->tt_aligned_block_memset(
+ (uintptr_t *)msg,
+ 0,sizeof(*msg));
+
+ msg->data.ipcinfo.ctrlsvc.type = attr->type;
+ msg->data.ipcinfo.ctrlsvc.subtype = attr->subtype;
+
+ msg->data.ipcinfo.ctrlsvc.keys.key[0] = attr->keys.key[0];
+ msg->data.ipcinfo.ctrlsvc.keys.key[1] = attr->keys.key[1];
+ msg->data.ipcinfo.ctrlsvc.keys.key[2] = attr->keys.key[2];
+ msg->data.ipcinfo.ctrlsvc.keys.key[3] = attr->keys.key[3];
+ msg->data.ipcinfo.ctrlsvc.keys.key[4] = attr->keys.key[4];
+ msg->data.ipcinfo.ctrlsvc.keys.key[5] = attr->keys.key[5];
+
+ __ntapi->tt_guid_copy(
+ &msg->data.ipcinfo.ctrlsvc.guid,
+ &attr->guid);
+}
+
+
+static void __ipc_init_ctrl_msg_semsvc(
+ nt_rtdata * rtdata,
+ nt_tty_ipc_msg * msg)
+{
+ __ntapi->tt_aligned_block_memset(
+ (uintptr_t *)msg,
+ 0,sizeof(*msg));
+
+ msg->data.ipcinfo.ctrlsvc.type = rtdata->semctl_type;
+ msg->data.ipcinfo.ctrlsvc.subtype = rtdata->semctl_subtype;
+
+ msg->data.ipcinfo.ctrlsvc.keys.key[0] = rtdata->semctl_keys[0];
+ msg->data.ipcinfo.ctrlsvc.keys.key[1] = rtdata->semctl_keys[1];
+ msg->data.ipcinfo.ctrlsvc.keys.key[2] = rtdata->semctl_keys[2];
+ msg->data.ipcinfo.ctrlsvc.keys.key[3] = rtdata->semctl_keys[3];
+ msg->data.ipcinfo.ctrlsvc.keys.key[4] = rtdata->semctl_keys[4];
+ msg->data.ipcinfo.ctrlsvc.keys.key[5] = rtdata->semctl_keys[5];
+
+ __ntapi->tt_guid_copy(
+ &msg->data.ipcinfo.ctrlsvc.guid,
+ &rtdata->semctl_guid);
+}
+
+
+static void __ipc_init_ctrl_msg_ipcpeer(
+ nt_rtdata * rtdata,
+ nt_tty_ipc_msg * msg)
+{
+ __ntapi->tt_aligned_block_memset(
+ (uintptr_t *)msg,
+ 0,sizeof(*msg));
+
+ msg->data.ipcinfo.ctrlsvc.type = rtdata->srv_type;
+ msg->data.ipcinfo.ctrlsvc.subtype = rtdata->srv_subtype;
+
+ msg->data.ipcinfo.ctrlsvc.keys.key[0] = rtdata->srv_keys[0];
+ msg->data.ipcinfo.ctrlsvc.keys.key[1] = rtdata->srv_keys[1];
+ msg->data.ipcinfo.ctrlsvc.keys.key[2] = rtdata->srv_keys[2];
+ msg->data.ipcinfo.ctrlsvc.keys.key[3] = rtdata->srv_keys[3];
+ msg->data.ipcinfo.ctrlsvc.keys.key[4] = rtdata->srv_keys[4];
+ msg->data.ipcinfo.ctrlsvc.keys.key[5] = rtdata->srv_keys[5];
+
+ __ntapi->tt_guid_copy(
+ &msg->data.ipcinfo.ctrlsvc.guid,
+ &rtdata->srv_guid);
+}
+
+
+static int32_t __ipc_set_client_keys(
+ void * hport,
+ const nt_port_attr * attr,
+ nt_rtdata * rtdata)
+{
+ int32_t status;
+ nt_tty_ipc_msg msg;
+ uint32_t opcode;
+
+ switch (attr->type) {
+ case NT_PORT_TYPE_SEMCTL:
+ if (rtdata->srv_type == NT_PORT_TYPE_SEMSVC)
+ __ipc_init_ctrl_msg_ipcpeer(
+ rtdata,&msg);
+ else
+ __ipc_init_ctrl_msg_semctl(
+ attr,&msg);
+
+ opcode = NT_TTY_SEM_FCNTL;
+ break;
+
+ case NT_PORT_TYPE_SEMSVC:
+ if (rtdata->srv_type == NT_PORT_TYPE_SEMCTL)
+ return NT_STATUS_SUCCESS;
+
+ __ipc_init_ctrl_msg_semsvc(
+ rtdata,&msg);
+
+ opcode = NT_TTY_SEM_FCNTL;
+ break;
+
+ default:
+ return NT_STATUS_SUCCESS;
+ }
+
+ 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.ipcinfo.ipckeys[0] = rtdata->ipc_keys[0];
+ msg.data.ipcinfo.ipckeys[1] = rtdata->ipc_keys[1];
+ msg.data.ipcinfo.ipckeys[2] = rtdata->ipc_keys[2];
+ msg.data.ipcinfo.ipckeys[3] = rtdata->ipc_keys[3];
+ msg.data.ipcinfo.ipckeys[4] = rtdata->ipc_keys[4];
+ msg.data.ipcinfo.ipckeys[5] = rtdata->ipc_keys[5];
+
+ if ((status = __ntapi->zw_request_wait_reply_port(hport,&msg,&msg)))
+ return status;
+ else if (msg.data.ttyinfo.status)
+ return msg.data.ttyinfo.status;
+
+ return NT_STATUS_SUCCESS;
+}
+
static int32_t __ipc_connect_by_attr(
void ** hport,
const nt_port_attr * attr,
nt_unicode_string * str,
void * hconn,
- __out void ** hsection,
- __out void ** secaddr,
- __out size_t * secsize)
+ void ** hsection,
+ void ** secaddr,
+ size_t * secsize,
+ int fexisting)
{
int32_t status;
struct dalist_node_ex * node;
@@ -35,10 +163,12 @@ static int32_t __ipc_connect_by_attr(
nt_port_attr * nconn;
nt_ipc_conn * ipc;
intptr_t * hlock;
+ nt_rtdata * rtdata;
ntapi_internals * __internals;
/* init */
__internals = __ntapi_internals();
+ rtdata = __internals->rtdata;
/* lock */
hlock = &(__internals->hlock);
@@ -76,6 +206,10 @@ static int32_t __ipc_connect_by_attr(
}
}
+ /* __ipc_get_port? */
+ if (fexisting)
+ return __ipc_connect_return(hlock,NT_STATUS_NOT_FOUND);
+
/* allocate list node */
if ((status = dalist_get_free_node(
&__internals->ipc_conns,
@@ -96,6 +230,41 @@ static int32_t __ipc_connect_by_attr(
}
}
+ /* server-to-server synchronization */
+ if (!rtdata->ipc_keys[0]) {
+ rtdata->ipc_keys[0] = __ntapi->tt_buffer_crc32(
+ (uint32_t)(uintptr_t)&hport,
+ (char *)__internals,sizeof(*__internals));
+
+ rtdata->ipc_keys[1] = __ntapi->tt_buffer_crc32(
+ (uint32_t)(uintptr_t)&hconn,
+ (char *)rtdata,sizeof(*rtdata));
+
+ rtdata->ipc_keys[2] = __ntapi->tt_buffer_crc32(
+ (uint32_t)(uintptr_t)&attr,
+ (char *)attr,sizeof(*attr));
+
+ rtdata->ipc_keys[3] = __ntapi->tt_buffer_crc32(
+ (uint32_t)(uintptr_t)&node,
+ (char *)node,sizeof(*node));
+
+ rtdata->ipc_keys[4] = __ntapi->tt_buffer_crc32(
+ (uint32_t)(uintptr_t)&str,
+ (char *)pe_get_peb_address(),
+ sizeof(nt_peb));
+
+ rtdata->ipc_keys[5] = __ntapi->tt_buffer_crc32(
+ (uint32_t)(uintptr_t)&conn,
+ (char *)pe_get_teb_address(),
+ sizeof(nt_tib));
+ }
+
+ if ((status = __ipc_set_client_keys(hconn,attr,rtdata))) {
+ __ntapi->zw_close(hconn);
+ dalist_deposit_free_node(&__internals->ipc_conns,node);
+ return __ipc_connect_return(hlock,status);
+ }
+
/* add connection */
node->key = (uintptr_t)hconn;
ipc = (nt_ipc_conn *)&node->dblock;
@@ -143,7 +312,7 @@ int32_t __stdcall __ntapi_ipc_connect_section_by_attr(
return __ipc_connect_by_attr(
hport,attr,&str,0,
- hsection,secaddr,secsize);
+ hsection,secaddr,secsize,0);
}
@@ -167,7 +336,7 @@ int32_t __stdcall __ntapi_ipc_connect_section_by_name(
return __ipc_connect_by_attr(
hport,&attr,&str,0,
- hsection,secaddr,secsize);
+ hsection,secaddr,secsize,0);
}
@@ -204,7 +373,7 @@ int32_t __stdcall __ntapi_ipc_connect_section_by_symlink(
return __ipc_connect_by_attr(
hport,&attr,str,0,
- hsection,secaddr,secsize);
+ hsection,secaddr,secsize,0);
}
@@ -217,7 +386,7 @@ int32_t __stdcall __ntapi_ipc_connect_section_by_port(
{
return __ipc_connect_by_attr(
&(void *){0},attr,0,hconn,
- hsection,secaddr,secsize);
+ hsection,secaddr,secsize,0);
}
@@ -298,6 +467,35 @@ int __ntapi_ipc_page_alloc(
}
+int32_t __stdcall __ntapi_ipc_get_port_by_attr(
+ __out void ** hport,
+ __in nt_port_attr * attr)
+{
+ return __ipc_connect_by_attr(
+ hport,attr,0,0,
+ &(void *){0},
+ &(void *){0},
+ &(size_t){0},
+ 1);
+}
+
+
+int32_t __stdcall __ntapi_ipc_get_port_section_by_attr(
+ __out void ** hport,
+ __in nt_port_attr * attr,
+ __out void ** hsection,
+ __out void ** section_addr,
+ __out size_t * section_size)
+{
+ return __ipc_connect_by_attr(
+ hport,attr,0,0,
+ hsection,
+ section_addr,
+ section_size,
+ 1);
+}
+
+
int32_t __stdcall __ntapi_ipc_init_section_by_port(
__in void * hconn,
__out void ** hsection,
diff --git a/src/process/ntapi_tt_fork.c b/src/process/ntapi_tt_fork.c
index d76a994..68ae84b 100644
--- a/src/process/ntapi_tt_fork.c
+++ b/src/process/ntapi_tt_fork.c
@@ -25,9 +25,11 @@ static intptr_t __fastcall __ntapi_tt_fork_finalize(
nt_oa oa;
nt_cid cid;
int page;
+ nt_rtdata * rtdata;
ntapi_internals * __internals;
__internals = __ntapi_internals();
+ rtdata = __internals->rtdata;
*hprocess = 0;
*hthread = 0;
@@ -73,6 +75,16 @@ static intptr_t __fastcall __ntapi_tt_fork_finalize(
__internals->ipc_pages[page],
NT_ALLOCATION_GRANULARITY);
+ rtdata->hsemctl = 0;
+ rtdata->hsempid = 0;
+
+ rtdata->ipc_keys[0] = 0;
+ rtdata->ipc_keys[1] = 0;
+ rtdata->ipc_keys[2] = 0;
+ rtdata->ipc_keys[3] = 0;
+ rtdata->ipc_keys[4] = 0;
+ rtdata->ipc_keys[5] = 0;
+
return 0;
}
diff --git a/src/sem/ntapi_sem_connect.c b/src/sem/ntapi_sem_connect.c
index 32c3610..2dc9a94 100644
--- a/src/sem/ntapi_sem_connect.c
+++ b/src/sem/ntapi_sem_connect.c
@@ -259,12 +259,17 @@ int32_t __stdcall __ntapi_sem_open(
__in uint32_t share,
__in uint32_t nslots)
{
- int32_t status;
- uint32_t key;
- uint32_t id;
- void * hsymlink;
- nt_oa ipcoa;
- void * hipc;
+ int32_t status;
+ uint32_t key;
+ uint32_t id;
+ void * hsymlink;
+ nt_oa ipcoa;
+ void * hipc;
+ nt_rtdata * rtdata;
+ nt_tty_service_info semctl;
+
+ /* init */
+ rtdata = (__ntapi_internals())->rtdata;
/* validate */
if (!oa->root_dir)
@@ -310,6 +315,19 @@ int32_t __stdcall __ntapi_sem_open(
return status;
}
+ /* 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;
+
/* ipc connect */
status = __ntapi->ipc_connect_by_symlink(
&hipc,hsymlink);
diff --git a/src/sem/ntapi_sem_fcntl.c b/src/sem/ntapi_sem_fcntl.c
index d48557f..d160e66 100644
--- a/src/sem/ntapi_sem_fcntl.c
+++ b/src/sem/ntapi_sem_fcntl.c
@@ -37,5 +37,6 @@ int32_t __stdcall __ntapi_sem_fcntl(
(void)output_buffer;
(void)output_buffer_length;
- return 0;
+ /* internal only */
+ return NT_STATUS_NOT_IMPLEMENTED;
}