diff options
Diffstat (limited to 'src/ipc')
-rw-r--r-- | src/ipc/ntapi_ipc_connect.c | 249 |
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; +} |