/********************************************************/ /* ntapi: Native API core library */ /* Copyright (C) 2013--2017 Z. Gilboa */ /* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */ /********************************************************/ #include #include #include #include #include #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; }