summaryrefslogtreecommitdiffhomepage
path: root/src/ipc
diff options
context:
space:
mode:
Diffstat (limited to 'src/ipc')
-rw-r--r--src/ipc/ntapi_ipc_connect.c249
1 files changed, 249 insertions, 0 deletions
diff --git a/src/ipc/ntapi_ipc_connect.c b/src/ipc/ntapi_ipc_connect.c
new file mode 100644
index 0000000..d61e869
--- /dev/null
+++ b/src/ipc/ntapi_ipc_connect.c
@@ -0,0 +1,249 @@
+/********************************************************/
+/* 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/ntapi.h>
+#include "ntapi_impl.h"
+
+static int32_t __ipc_connect_return(
+ intptr_t * hlock,
+ int32_t status)
+{
+ at_store(hlock,0);
+ return status;
+}
+
+
+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)
+{
+ int32_t status;
+ struct dalist_node_ex * node;
+ const nt_port_attr * conn;
+ nt_port_attr * nconn;
+ nt_ipc_conn * ipc;
+ intptr_t * hlock;
+ ntapi_internals * __internals;
+
+ /* init */
+ __internals = __ntapi_internals();
+
+ /* lock */
+ hlock = &(__internals->hlock);
+
+ if (at_locked_cas(hlock,0,1))
+ return NT_STATUS_RESOURCE_NOT_OWNED;
+
+ /* already connected? */
+ node = (struct dalist_node_ex *)__internals->ipc_conns.head;
+
+ for (; node; node=node->next) {
+ ipc = (nt_ipc_conn *)&node->dblock;
+ conn = &ipc->attr;
+
+ if ((attr->keys.key[0] == conn->keys.key[0])
+ && (attr->keys.key[1] == conn->keys.key[1])
+ && (attr->keys.key[2] == conn->keys.key[2])
+ && (attr->keys.key[3] == conn->keys.key[3])
+ && (attr->keys.key[4] == conn->keys.key[4])
+ && (attr->keys.key[5] == conn->keys.key[5])
+ && !__ntapi->tt_guid_compare(
+ &attr->guid,
+ &conn->guid)) {
+ /* already connected */
+ if (hconn)
+ return __ipc_connect_return(
+ hlock,
+ ((uintptr_t)hconn == node->key)
+ ? NT_STATUS_SUCCESS
+ : NT_STATUS_CONTEXT_MISMATCH);
+
+ *hport = (void *)node->key;
+ *hsection = ipc->hsection;
+ *secaddr = ipc->secaddr;
+ *secsize = ipc->secsize;
+
+ return __ipc_connect_return(hlock,NT_STATUS_SUCCESS);
+ }
+ }
+
+ /* allocate list node */
+ if ((status = dalist_get_free_node(
+ &__internals->ipc_conns,
+ (void **)&node)))
+ return __ipc_connect_return(hlock,status);
+
+ /* connect as needed */
+ if (!hconn) {
+ status = __ntapi->zw_connect_port(
+ &hconn,str,0,0,0,0,0,0);
+
+ if (status) {
+ 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;
+ nconn = &ipc->attr;
+
+ __ntapi->tt_aligned_block_memcpy(
+ (uintptr_t *)nconn,
+ (uintptr_t *)attr,
+ sizeof(nt_port_attr));
+
+ ipc->hsection = 0;
+ ipc->secaddr = 0;
+ ipc->secsize = 0;
+
+ dalist_insert_node_by_key(
+ &__internals->ipc_conns,
+ node);
+
+ /* all done */
+ *hport = hconn;
+ *hsection = 0;
+ *secaddr = 0;
+ *secsize = 0;
+
+ return __ipc_connect_return(hlock,NT_STATUS_SUCCESS);
+}
+
+
+int32_t __stdcall __ntapi_ipc_connect_by_attr(
+ __out void ** hport,
+ __in nt_port_attr * attr)
+{
+ nt_port_name name;
+ nt_unicode_string str;
+
+ __ntapi->tt_port_name_from_attr(
+ &name,attr);
+
+ str.strlen = ((size_t)&(((nt_port_name *)0)->null_termination));
+ str.maxlen = 0;
+ str.buffer = &name.base_named_objects[0];
+
+ return __ipc_connect_by_attr(
+ hport,attr,&str,0,
+ &(void *){0},
+ &(void *){0},
+ &(size_t){0});
+}
+
+
+int32_t __stdcall __ntapi_ipc_connect_by_name(
+ __out void ** hport,
+ __in nt_port_name * name)
+{
+ int32_t status;
+ nt_port_attr attr;
+ nt_unicode_string str;
+
+ if ((status = __ntapi->tt_port_attr_from_name(&attr,name)))
+ return status;
+
+ str.strlen = ((size_t)&(((nt_port_name *)0)->null_termination));
+ str.maxlen = 0;
+ str.buffer = &name->base_named_objects[0];
+
+ return __ipc_connect_by_attr(
+ hport,&attr,&str,0,
+ &(void *){0},
+ &(void *){0},
+ &(size_t){0});
+}
+
+
+int32_t __stdcall __ntapi_ipc_connect_by_symlink(
+ __out void ** hport,
+ __in void * hsymlink)
+{
+ int32_t status;
+ nt_port_attr attr;
+ nt_port_name * name;
+ size_t namelen;
+ uintptr_t buffer[512/sizeof(uintptr_t)];
+ nt_unicode_string * str;
+
+ str = (nt_unicode_string *)buffer;
+ str->strlen = 0;
+ str->maxlen = sizeof(buffer) - sizeof(nt_unicode_string);
+ str->buffer = (wchar16_t *)&str[1];
+
+ if ((status = __ntapi->zw_query_symbolic_link_object(
+ hsymlink,str,&namelen)))
+ return status;
+
+ if (str->strlen != ((size_t)&(((nt_port_name *)0)->null_termination)))
+ return NT_STATUS_INVALID_PORT_ATTRIBUTES;
+
+ name = (nt_port_name *)str->buffer;
+
+ if ((status = __ntapi->tt_port_attr_from_name(&attr,name)))
+ return status;
+
+ return __ipc_connect_by_attr(
+ hport,&attr,str,0,
+ &(void *){0},
+ &(void *){0},
+ &(size_t){0});
+}
+
+
+int32_t __stdcall __ntapi_ipc_connect_by_port(
+ __in void * hconn,
+ __in nt_port_attr * attr)
+{
+ return __ipc_connect_by_attr(
+ &(void *){0},attr,0,hconn,
+ &(void *){0},
+ &(void *){0},
+ &(size_t){0});
+}
+
+
+int __ntapi_ipc_page_alloc(
+ struct dalist_ex * dlist,
+ void ** addr,
+ size_t * alloc_size)
+{
+ int32_t status;
+ ntapi_internals * __internals;
+
+ __internals = __ntapi_internals();
+
+ if (__internals->ipc_page == __NT_IPC_PAGES)
+ return NT_STATUS_QUOTA_EXCEEDED;
+
+ if ((status = __ntapi->zw_allocate_virtual_memory(
+ NT_CURRENT_PROCESS_HANDLE,
+ addr,0,alloc_size,
+ NT_MEM_COMMIT,
+ NT_PAGE_READWRITE)))
+ return status;
+
+ dalist_deposit_memory_block(
+ dlist,*addr,*alloc_size);
+
+ __internals->ipc_pages[__internals->ipc_page++] = *addr;
+
+ return 0;
+}