Blame src/ipc/ntapi_ipc_connect.c

30d28d
/********************************************************/
30d28d
/*  ntapi: Native API core library                      */
30d28d
/*  Copyright (C) 2013--2017  Z. Gilboa                 */
30d28d
/*  Released under GPLv2 and GPLv3; see COPYING.NTAPI.  */
30d28d
/********************************************************/
30d28d
30d28d
#include <psxtypes/psxtypes.h>
30d28d
#include <ntapi/nt_file.h>
30d28d
#include <ntapi/nt_string.h>
30d28d
#include <ntapi/nt_atomic.h>
30d28d
#include <ntapi/ntapi.h>
30d28d
#include "ntapi_impl.h"
30d28d
30d28d
static int32_t __ipc_connect_return(
30d28d
	intptr_t *	hlock,
30d28d
	int32_t		status)
30d28d
{
30d28d
	at_store(hlock,0);
30d28d
	return status;
30d28d
}
30d28d
30d28d
edb085
static void __ipc_init_ctrl_msg_semctl(
edb085
	const nt_port_attr *	attr,
edb085
	nt_tty_ipc_msg *	msg)
edb085
{
edb085
	__ntapi->tt_aligned_block_memset(
edb085
		(uintptr_t *)msg,
edb085
		0,sizeof(*msg));
edb085
edb085
	msg->data.ipcinfo.ctrlsvc.type          = attr->type;
edb085
	msg->data.ipcinfo.ctrlsvc.subtype       = attr->subtype;
edb085
edb085
	msg->data.ipcinfo.ctrlsvc.keys.key[0]   = attr->keys.key[0];
edb085
	msg->data.ipcinfo.ctrlsvc.keys.key[1]   = attr->keys.key[1];
edb085
	msg->data.ipcinfo.ctrlsvc.keys.key[2]   = attr->keys.key[2];
edb085
	msg->data.ipcinfo.ctrlsvc.keys.key[3]   = attr->keys.key[3];
edb085
	msg->data.ipcinfo.ctrlsvc.keys.key[4]   = attr->keys.key[4];
edb085
	msg->data.ipcinfo.ctrlsvc.keys.key[5]   = attr->keys.key[5];
edb085
edb085
	__ntapi->tt_guid_copy(
edb085
		&msg->data.ipcinfo.ctrlsvc.guid,
edb085
		&attr->guid);
edb085
}
edb085
edb085
edb085
static void __ipc_init_ctrl_msg_semsvc(
edb085
	nt_rtdata *		rtdata,
edb085
	nt_tty_ipc_msg *	msg)
edb085
{
edb085
	__ntapi->tt_aligned_block_memset(
edb085
		(uintptr_t *)msg,
edb085
		0,sizeof(*msg));
edb085
edb085
	msg->data.ipcinfo.ctrlsvc.type          = rtdata->semctl_type;
edb085
	msg->data.ipcinfo.ctrlsvc.subtype       = rtdata->semctl_subtype;
edb085
edb085
	msg->data.ipcinfo.ctrlsvc.keys.key[0]   = rtdata->semctl_keys[0];
edb085
	msg->data.ipcinfo.ctrlsvc.keys.key[1]   = rtdata->semctl_keys[1];
edb085
	msg->data.ipcinfo.ctrlsvc.keys.key[2]   = rtdata->semctl_keys[2];
edb085
	msg->data.ipcinfo.ctrlsvc.keys.key[3]   = rtdata->semctl_keys[3];
edb085
	msg->data.ipcinfo.ctrlsvc.keys.key[4]   = rtdata->semctl_keys[4];
edb085
	msg->data.ipcinfo.ctrlsvc.keys.key[5]   = rtdata->semctl_keys[5];
edb085
edb085
	__ntapi->tt_guid_copy(
edb085
		&msg->data.ipcinfo.ctrlsvc.guid,
edb085
		&rtdata->semctl_guid);
edb085
}
edb085
edb085
47f21a
static void __ipc_init_ctrl_msg_msqctl(
47f21a
	const nt_port_attr *	attr,
47f21a
	nt_tty_ipc_msg *	msg)
47f21a
{
47f21a
	__ntapi->tt_aligned_block_memset(
47f21a
		(uintptr_t *)msg,
47f21a
		0,sizeof(*msg));
47f21a
47f21a
	msg->data.ipcinfo.ctrlsvc.type          = attr->type;
47f21a
	msg->data.ipcinfo.ctrlsvc.subtype       = attr->subtype;
47f21a
47f21a
	msg->data.ipcinfo.ctrlsvc.keys.key[0]   = attr->keys.key[0];
47f21a
	msg->data.ipcinfo.ctrlsvc.keys.key[1]   = attr->keys.key[1];
47f21a
	msg->data.ipcinfo.ctrlsvc.keys.key[2]   = attr->keys.key[2];
47f21a
	msg->data.ipcinfo.ctrlsvc.keys.key[3]   = attr->keys.key[3];
47f21a
	msg->data.ipcinfo.ctrlsvc.keys.key[4]   = attr->keys.key[4];
47f21a
	msg->data.ipcinfo.ctrlsvc.keys.key[5]   = attr->keys.key[5];
47f21a
47f21a
	__ntapi->tt_guid_copy(
47f21a
		&msg->data.ipcinfo.ctrlsvc.guid,
47f21a
		&attr->guid);
47f21a
}
47f21a
47f21a
47f21a
static void __ipc_init_ctrl_msg_msqsvc(
47f21a
	nt_rtdata *		rtdata,
47f21a
	nt_tty_ipc_msg *	msg)
47f21a
{
47f21a
	__ntapi->tt_aligned_block_memset(
47f21a
		(uintptr_t *)msg,
47f21a
		0,sizeof(*msg));
47f21a
47f21a
	msg->data.ipcinfo.ctrlsvc.type          = rtdata->msqctl_type;
47f21a
	msg->data.ipcinfo.ctrlsvc.subtype       = rtdata->msqctl_subtype;
47f21a
47f21a
	msg->data.ipcinfo.ctrlsvc.keys.key[0]   = rtdata->msqctl_keys[0];
47f21a
	msg->data.ipcinfo.ctrlsvc.keys.key[1]   = rtdata->msqctl_keys[1];
47f21a
	msg->data.ipcinfo.ctrlsvc.keys.key[2]   = rtdata->msqctl_keys[2];
47f21a
	msg->data.ipcinfo.ctrlsvc.keys.key[3]   = rtdata->msqctl_keys[3];
47f21a
	msg->data.ipcinfo.ctrlsvc.keys.key[4]   = rtdata->msqctl_keys[4];
47f21a
	msg->data.ipcinfo.ctrlsvc.keys.key[5]   = rtdata->msqctl_keys[5];
47f21a
47f21a
	__ntapi->tt_guid_copy(
47f21a
		&msg->data.ipcinfo.ctrlsvc.guid,
47f21a
		&rtdata->msqctl_guid);
47f21a
}
47f21a
47f21a
b92a12
static void __ipc_init_ctrl_msg_aflctl(
b92a12
	const nt_port_attr *	attr,
b92a12
	nt_tty_ipc_msg *	msg)
b92a12
{
b92a12
	__ntapi->tt_aligned_block_memset(
b92a12
		(uintptr_t *)msg,
b92a12
		0,sizeof(*msg));
b92a12
b92a12
	msg->data.ipcinfo.ctrlsvc.type          = attr->type;
b92a12
	msg->data.ipcinfo.ctrlsvc.subtype       = attr->subtype;
b92a12
b92a12
	msg->data.ipcinfo.ctrlsvc.keys.key[0]   = attr->keys.key[0];
b92a12
	msg->data.ipcinfo.ctrlsvc.keys.key[1]   = attr->keys.key[1];
b92a12
	msg->data.ipcinfo.ctrlsvc.keys.key[2]   = attr->keys.key[2];
b92a12
	msg->data.ipcinfo.ctrlsvc.keys.key[3]   = attr->keys.key[3];
b92a12
	msg->data.ipcinfo.ctrlsvc.keys.key[4]   = attr->keys.key[4];
b92a12
	msg->data.ipcinfo.ctrlsvc.keys.key[5]   = attr->keys.key[5];
b92a12
b92a12
	__ntapi->tt_guid_copy(
b92a12
		&msg->data.ipcinfo.ctrlsvc.guid,
b92a12
		&attr->guid);
b92a12
}
b92a12
b92a12
b92a12
static void __ipc_init_ctrl_msg_aflsvc(
b92a12
	nt_rtdata *		rtdata,
b92a12
	nt_tty_ipc_msg *	msg)
b92a12
{
b92a12
	__ntapi->tt_aligned_block_memset(
b92a12
		(uintptr_t *)msg,
b92a12
		0,sizeof(*msg));
b92a12
b92a12
	msg->data.ipcinfo.ctrlsvc.type          = rtdata->aflctl_type;
b92a12
	msg->data.ipcinfo.ctrlsvc.subtype       = rtdata->aflctl_subtype;
b92a12
b92a12
	msg->data.ipcinfo.ctrlsvc.keys.key[0]   = rtdata->aflctl_keys[0];
b92a12
	msg->data.ipcinfo.ctrlsvc.keys.key[1]   = rtdata->aflctl_keys[1];
b92a12
	msg->data.ipcinfo.ctrlsvc.keys.key[2]   = rtdata->aflctl_keys[2];
b92a12
	msg->data.ipcinfo.ctrlsvc.keys.key[3]   = rtdata->aflctl_keys[3];
b92a12
	msg->data.ipcinfo.ctrlsvc.keys.key[4]   = rtdata->aflctl_keys[4];
b92a12
	msg->data.ipcinfo.ctrlsvc.keys.key[5]   = rtdata->aflctl_keys[5];
b92a12
b92a12
	__ntapi->tt_guid_copy(
b92a12
		&msg->data.ipcinfo.ctrlsvc.guid,
b92a12
		&rtdata->aflctl_guid);
b92a12
}
b92a12
b92a12
edb085
static void __ipc_init_ctrl_msg_ipcpeer(
edb085
	nt_rtdata *		rtdata,
edb085
	nt_tty_ipc_msg *	msg)
edb085
{
edb085
	__ntapi->tt_aligned_block_memset(
edb085
		(uintptr_t *)msg,
edb085
		0,sizeof(*msg));
edb085
edb085
	msg->data.ipcinfo.ctrlsvc.type          = rtdata->srv_type;
edb085
	msg->data.ipcinfo.ctrlsvc.subtype       = rtdata->srv_subtype;
edb085
edb085
	msg->data.ipcinfo.ctrlsvc.keys.key[0]   = rtdata->srv_keys[0];
edb085
	msg->data.ipcinfo.ctrlsvc.keys.key[1]   = rtdata->srv_keys[1];
edb085
	msg->data.ipcinfo.ctrlsvc.keys.key[2]   = rtdata->srv_keys[2];
edb085
	msg->data.ipcinfo.ctrlsvc.keys.key[3]   = rtdata->srv_keys[3];
edb085
	msg->data.ipcinfo.ctrlsvc.keys.key[4]   = rtdata->srv_keys[4];
edb085
	msg->data.ipcinfo.ctrlsvc.keys.key[5]   = rtdata->srv_keys[5];
edb085
edb085
	__ntapi->tt_guid_copy(
edb085
		&msg->data.ipcinfo.ctrlsvc.guid,
edb085
		&rtdata->srv_guid);
edb085
}
edb085
edb085
edb085
static int32_t __ipc_set_client_keys(
edb085
	void *			hport,
edb085
	const nt_port_attr *	attr,
edb085
	nt_rtdata *		rtdata)
edb085
{
edb085
	int32_t			status;
edb085
	nt_tty_ipc_msg		msg;
edb085
	uint32_t		opcode;
edb085
edb085
	switch (attr->type) {
edb085
		case NT_PORT_TYPE_SEMCTL:
edb085
			if (rtdata->srv_type == NT_PORT_TYPE_SEMSVC)
edb085
				__ipc_init_ctrl_msg_ipcpeer(
edb085
					rtdata,&msg;;
edb085
			else
edb085
				__ipc_init_ctrl_msg_semctl(
edb085
					attr,&msg;;
edb085
edb085
			opcode = NT_TTY_SEM_FCNTL;
edb085
			break;
edb085
edb085
		case NT_PORT_TYPE_SEMSVC:
edb085
			if (rtdata->srv_type == NT_PORT_TYPE_SEMCTL)
edb085
				return NT_STATUS_SUCCESS;
edb085
edb085
			__ipc_init_ctrl_msg_semsvc(
edb085
				rtdata,&msg;;
edb085
edb085
			opcode = NT_TTY_SEM_FCNTL;
edb085
			break;
edb085
47f21a
		case NT_PORT_TYPE_MSQCTL:
47f21a
			if (rtdata->srv_type == NT_PORT_TYPE_MSQSVC)
47f21a
				__ipc_init_ctrl_msg_ipcpeer(
47f21a
					rtdata,&msg;;
47f21a
			else
47f21a
				__ipc_init_ctrl_msg_msqctl(
47f21a
					attr,&msg;;
47f21a
47f21a
			opcode = NT_TTY_MSQ_FCNTL;
47f21a
			break;
47f21a
47f21a
		case NT_PORT_TYPE_MSQSVC:
47f21a
			if (rtdata->srv_type == NT_PORT_TYPE_MSQCTL)
47f21a
				return NT_STATUS_SUCCESS;
47f21a
47f21a
			__ipc_init_ctrl_msg_msqsvc(
47f21a
				rtdata,&msg;;
47f21a
47f21a
			opcode = NT_TTY_MSQ_FCNTL;
47f21a
			break;
47f21a
b92a12
		case NT_PORT_TYPE_AFLCTL:
b92a12
			if (rtdata->srv_type == NT_PORT_TYPE_AFLSVC)
b92a12
				__ipc_init_ctrl_msg_ipcpeer(
b92a12
					rtdata,&msg;;
b92a12
			else
b92a12
				__ipc_init_ctrl_msg_aflctl(
b92a12
					attr,&msg;;
b92a12
b92a12
			opcode = NT_TTY_AFL_FCNTL;
b92a12
			break;
b92a12
b92a12
		case NT_PORT_TYPE_AFLSVC:
b92a12
			if (rtdata->srv_type == NT_PORT_TYPE_AFLCTL)
b92a12
				return NT_STATUS_SUCCESS;
b92a12
b92a12
			__ipc_init_ctrl_msg_aflsvc(
b92a12
				rtdata,&msg;;
b92a12
b92a12
			opcode = NT_TTY_AFL_FCNTL;
b92a12
			break;
b92a12
edb085
		default:
edb085
			return NT_STATUS_SUCCESS;
edb085
	}
edb085
edb085
	msg.header.msg_type		= NT_LPC_NEW_MESSAGE;
edb085
	msg.header.data_size		= sizeof(msg.data);
edb085
	msg.header.msg_size		= sizeof(msg);
edb085
	msg.data.ttyinfo.opcode		= opcode;
edb085
edb085
	msg.data.ipcinfo.ipckeys[0]     = rtdata->ipc_keys[0];
edb085
	msg.data.ipcinfo.ipckeys[1]     = rtdata->ipc_keys[1];
edb085
	msg.data.ipcinfo.ipckeys[2]     = rtdata->ipc_keys[2];
edb085
	msg.data.ipcinfo.ipckeys[3]     = rtdata->ipc_keys[3];
edb085
	msg.data.ipcinfo.ipckeys[4]     = rtdata->ipc_keys[4];
edb085
	msg.data.ipcinfo.ipckeys[5]     = rtdata->ipc_keys[5];
edb085
edb085
	if ((status = __ntapi->zw_request_wait_reply_port(hport,&msg,&msg)))
edb085
		return status;
edb085
	else if (msg.data.ttyinfo.status)
edb085
		return msg.data.ttyinfo.status;
edb085
edb085
	return NT_STATUS_SUCCESS;
edb085
}
edb085
30d28d
static int32_t __ipc_connect_by_attr(
30d28d
	void **			hport,
30d28d
	const nt_port_attr *	attr,
30d28d
	nt_unicode_string *	str,
30d28d
	void *			hconn,
edb085
	void **			hsection,
edb085
	void **			secaddr,
edb085
	size_t *		secsize,
edb085
	int			fexisting)
30d28d
{
30d28d
	int32_t			status;
30d28d
	struct dalist_node_ex *	node;
30d28d
	const nt_port_attr *	conn;
30d28d
	nt_port_attr *		nconn;
30d28d
	nt_ipc_conn *		ipc;
30d28d
	intptr_t *		hlock;
edb085
	nt_rtdata *		rtdata;
30d28d
	ntapi_internals *	__internals;
30d28d
30d28d
	/* init */
30d28d
	__internals = __ntapi_internals();
edb085
	rtdata      = __internals->rtdata;
30d28d
30d28d
	/* lock */
30d28d
	hlock = &(__internals->hlock);
30d28d
da8524
        while (at_locked_cas(hlock,0,1))
da8524
		__ntapi->zw_delay_execution(
da8524
			NT_SYNC_NON_ALERTABLE,
da8524
			&(nt_timeout){{0,0}});
30d28d
30d28d
	/* already connected? */
30d28d
	node = (struct dalist_node_ex *)__internals->ipc_conns.head;
30d28d
30d28d
	for (; node; node=node->next) {
30d28d
		ipc  = (nt_ipc_conn *)&node->dblock;
30d28d
		conn = &ipc->attr;
30d28d
30d28d
		if ((attr->keys.key[0] == conn->keys.key[0])
30d28d
				&& (attr->keys.key[1] == conn->keys.key[1])
30d28d
				&& (attr->keys.key[2] == conn->keys.key[2])
30d28d
				&& (attr->keys.key[3] == conn->keys.key[3])
30d28d
				&& (attr->keys.key[4] == conn->keys.key[4])
30d28d
				&& (attr->keys.key[5] == conn->keys.key[5])
30d28d
				&& !__ntapi->tt_guid_compare(
30d28d
					&attr->guid,
30d28d
					&conn->guid)) {
30d28d
			/* already connected */
93e3aa
			if (hconn && ((uintptr_t)hconn != node->key))
30d28d
				return __ipc_connect_return(
93e3aa
					hlock,NT_STATUS_CONTEXT_MISMATCH);
30d28d
30d28d
			*hport    = (void *)node->key;
30d28d
			*hsection = ipc->hsection;
30d28d
			*secaddr  = ipc->secaddr;
30d28d
			*secsize  = ipc->secsize;
30d28d
30d28d
			return __ipc_connect_return(hlock,NT_STATUS_SUCCESS);
30d28d
		}
30d28d
	}
30d28d
edb085
	/* __ipc_get_port? */
edb085
	if (fexisting)
edb085
		return __ipc_connect_return(hlock,NT_STATUS_NOT_FOUND);
edb085
30d28d
	/* allocate list node */
30d28d
        if ((status = dalist_get_free_node(
30d28d
			&__internals->ipc_conns,
30d28d
			(void **)&node)))
30d28d
		return __ipc_connect_return(hlock,status);
30d28d
30d28d
	/* connect as needed */
30d28d
	if (!hconn) {
30d28d
		status = __ntapi->zw_connect_port(
30d28d
			&hconn,str,0,0,0,0,0,0);
30d28d
30d28d
		if (status) {
30d28d
			dalist_deposit_free_node(
30d28d
				&__internals->ipc_conns,
30d28d
				node);
30d28d
30d28d
			return __ipc_connect_return(hlock,status);
30d28d
		}
30d28d
	}
30d28d
edb085
	/* server-to-server synchronization */
edb085
	if (!rtdata->ipc_keys[0]) {
edb085
		rtdata->ipc_keys[0] = __ntapi->tt_buffer_crc32(
edb085
			(uint32_t)(uintptr_t)&hport,
edb085
			(char *)__internals,sizeof(*__internals));
edb085
edb085
		rtdata->ipc_keys[1] = __ntapi->tt_buffer_crc32(
edb085
			(uint32_t)(uintptr_t)&hconn,
edb085
			(char *)rtdata,sizeof(*rtdata));
edb085
edb085
		rtdata->ipc_keys[2] = __ntapi->tt_buffer_crc32(
edb085
			(uint32_t)(uintptr_t)&attr,
edb085
			(char *)attr,sizeof(*attr));
edb085
edb085
		rtdata->ipc_keys[3] = __ntapi->tt_buffer_crc32(
edb085
			(uint32_t)(uintptr_t)&node,
edb085
			(char *)node,sizeof(*node));
edb085
edb085
		rtdata->ipc_keys[4] = __ntapi->tt_buffer_crc32(
edb085
			(uint32_t)(uintptr_t)&str,
edb085
			(char *)pe_get_peb_address(),
edb085
			sizeof(nt_peb));
edb085
edb085
		rtdata->ipc_keys[5] = __ntapi->tt_buffer_crc32(
edb085
			(uint32_t)(uintptr_t)&conn,
edb085
			(char *)pe_get_teb_address(),
edb085
			sizeof(nt_tib));
edb085
	}
edb085
edb085
	if ((status = __ipc_set_client_keys(hconn,attr,rtdata))) {
edb085
		__ntapi->zw_close(hconn);
edb085
		dalist_deposit_free_node(&__internals->ipc_conns,node);
edb085
		return __ipc_connect_return(hlock,status);
edb085
	}
edb085
30d28d
	/* add connection */
30d28d
	node->key = (uintptr_t)hconn;
30d28d
	ipc   = (nt_ipc_conn *)&node->dblock;
30d28d
	nconn = &ipc->attr;
30d28d
30d28d
	__ntapi->tt_aligned_block_memcpy(
30d28d
		(uintptr_t *)nconn,
30d28d
		(uintptr_t *)attr,
30d28d
		sizeof(nt_port_attr));
30d28d
30d28d
	ipc->hsection = 0;
30d28d
	ipc->secaddr  = 0;
30d28d
	ipc->secsize  = 0;
30d28d
30d28d
	dalist_insert_node_by_key(
30d28d
		&__internals->ipc_conns,
30d28d
		node);
30d28d
30d28d
	/* all done */
30d28d
	*hport    = hconn;
30d28d
	*hsection = 0;
30d28d
	*secaddr  = 0;
30d28d
	*secsize  = 0;
30d28d
30d28d
	return __ipc_connect_return(hlock,NT_STATUS_SUCCESS);
30d28d
}
30d28d
30d28d
1b6aec
int32_t __stdcall __ntapi_ipc_connect_section_by_attr(
30d28d
	__out	void **		hport,
1b6aec
	__in	nt_port_attr *	attr,
1b6aec
	__out	void **		hsection,
1b6aec
	__out	void **		secaddr,
1b6aec
	__out	size_t *	secsize)
30d28d
{
30d28d
	nt_port_name		name;
30d28d
	nt_unicode_string	str;
30d28d
30d28d
	__ntapi->tt_port_name_from_attr(
30d28d
		&name,attr);
30d28d
30d28d
	str.strlen = ((size_t)&(((nt_port_name *)0)->null_termination));
30d28d
	str.maxlen = 0;
30d28d
	str.buffer = &name.base_named_objects[0];
30d28d
30d28d
	return __ipc_connect_by_attr(
30d28d
		hport,attr,&str,0,
edb085
		hsection,secaddr,secsize,0);
30d28d
}
30d28d
30d28d
1b6aec
int32_t __stdcall __ntapi_ipc_connect_section_by_name(
30d28d
	__out	void **		hport,
1b6aec
	__in	nt_port_name *	name,
1b6aec
	__out	void **		hsection,
1b6aec
	__out	void **		secaddr,
1b6aec
	__out	size_t *	secsize)
30d28d
{
30d28d
	int32_t			status;
30d28d
	nt_port_attr		attr;
30d28d
	nt_unicode_string	str;
30d28d
30d28d
	if ((status = __ntapi->tt_port_attr_from_name(&attr,name)))
30d28d
		return status;
30d28d
30d28d
	str.strlen = ((size_t)&(((nt_port_name *)0)->null_termination));
30d28d
	str.maxlen = 0;
30d28d
	str.buffer = &name->base_named_objects[0];
30d28d
30d28d
	return __ipc_connect_by_attr(
30d28d
		hport,&attr,&str,0,
edb085
		hsection,secaddr,secsize,0);
30d28d
}
30d28d
30d28d
1b6aec
int32_t __stdcall __ntapi_ipc_connect_section_by_symlink(
30d28d
	__out	void **		hport,
1b6aec
	__in	void *		hsymlink,
1b6aec
	__out	void **		hsection,
1b6aec
	__out	void **		secaddr,
1b6aec
	__out	size_t *	secsize)
30d28d
{
30d28d
	int32_t			status;
30d28d
	nt_port_attr		attr;
30d28d
	nt_port_name *		name;
30d28d
	size_t			namelen;
30d28d
	uintptr_t		buffer[512/sizeof(uintptr_t)];
30d28d
	nt_unicode_string *	str;
30d28d
30d28d
	str         = (nt_unicode_string *)buffer;
30d28d
	str->strlen = 0;
30d28d
	str->maxlen = sizeof(buffer) - sizeof(nt_unicode_string);
30d28d
	str->buffer = (wchar16_t *)&str[1];
30d28d
30d28d
	if ((status = __ntapi->zw_query_symbolic_link_object(
30d28d
			hsymlink,str,&namelen)))
30d28d
		return status;
30d28d
30d28d
	if (str->strlen != ((size_t)&(((nt_port_name *)0)->null_termination)))
30d28d
		return NT_STATUS_INVALID_PORT_ATTRIBUTES;
30d28d
30d28d
	name = (nt_port_name *)str->buffer;
30d28d
30d28d
	if ((status = __ntapi->tt_port_attr_from_name(&attr,name)))
30d28d
		return status;
30d28d
30d28d
	return __ipc_connect_by_attr(
30d28d
		hport,&attr,str,0,
edb085
		hsection,secaddr,secsize,0);
1b6aec
}
1b6aec
1b6aec
1b6aec
int32_t __stdcall __ntapi_ipc_connect_section_by_port(
1b6aec
	__in	void *		hconn,
1b6aec
	__in	nt_port_attr *	attr,
1b6aec
	__out	void **		hsection,
1b6aec
	__out	void **		secaddr,
1b6aec
	__out	size_t *	secsize)
1b6aec
{
1b6aec
	return __ipc_connect_by_attr(
1b6aec
		&(void *){0},attr,0,hconn,
edb085
		hsection,secaddr,secsize,0);
1b6aec
}
1b6aec
1b6aec
1b6aec
int32_t __stdcall __ntapi_ipc_connect_by_attr(
1b6aec
	__out	void **		hport,
1b6aec
	__in	nt_port_attr *	attr)
1b6aec
{
1b6aec
	return __ntapi_ipc_connect_section_by_attr(
1b6aec
		hport,attr,
1b6aec
		&(void *){0},
1b6aec
		&(void *){0},
1b6aec
		&(size_t){0});
1b6aec
}
1b6aec
1b6aec
1b6aec
int32_t __stdcall __ntapi_ipc_connect_by_name(
1b6aec
	__out	void **		hport,
1b6aec
	__in	nt_port_name *	name)
1b6aec
{
1b6aec
	return __ntapi_ipc_connect_section_by_name(
1b6aec
		hport,name,
1b6aec
		&(void *){0},
1b6aec
		&(void *){0},
1b6aec
		&(size_t){0});
1b6aec
}
1b6aec
1b6aec
1b6aec
int32_t __stdcall __ntapi_ipc_connect_by_symlink(
1b6aec
	__out	void **		hport,
1b6aec
	__in	void *		hsymlink)
1b6aec
{
1b6aec
	return __ntapi_ipc_connect_section_by_symlink(
1b6aec
		hport,hsymlink,
30d28d
		&(void *){0},
30d28d
		&(void *){0},
30d28d
		&(size_t){0});
30d28d
}
30d28d
30d28d
30d28d
int32_t __stdcall __ntapi_ipc_connect_by_port(
30d28d
	__in	void *		hconn,
30d28d
	__in	nt_port_attr *	attr)
30d28d
{
1b6aec
	return __ntapi_ipc_connect_section_by_port(
1b6aec
		hconn,attr,
30d28d
		&(void *){0},
30d28d
		&(void *){0},
30d28d
		&(size_t){0});
30d28d
}
30d28d
30d28d
30d28d
int __ntapi_ipc_page_alloc(
30d28d
	struct dalist_ex *	dlist,
30d28d
	void **			addr,
30d28d
	size_t *		alloc_size)
30d28d
{
30d28d
	int32_t			status;
40b623
	size_t			size;
30d28d
	ntapi_internals *	__internals;
30d28d
30d28d
	__internals = __ntapi_internals();
40b623
	size        = __NT_INTERNAL_PAGE_SIZE;
30d28d
30d28d
	if (__internals->ipc_page == __NT_IPC_PAGES)
30d28d
		return NT_STATUS_QUOTA_EXCEEDED;
30d28d
30d28d
	if ((status = __ntapi->zw_allocate_virtual_memory(
30d28d
			NT_CURRENT_PROCESS_HANDLE,
40b623
			addr,0,&size,
30d28d
			NT_MEM_COMMIT,
30d28d
			NT_PAGE_READWRITE)))
30d28d
		return status;
30d28d
30d28d
	dalist_deposit_memory_block(
40b623
		dlist,*addr,size);
30d28d
30d28d
	__internals->ipc_pages[__internals->ipc_page++] = *addr;
30d28d
40b623
	*alloc_size = size;
40b623
30d28d
	return 0;
30d28d
}
1b6aec
1b6aec
edb085
int32_t __stdcall __ntapi_ipc_get_port_by_attr(
edb085
	__out	void **			hport,
edb085
	__in	nt_port_attr *		attr)
edb085
{
edb085
	return __ipc_connect_by_attr(
edb085
		hport,attr,0,0,
edb085
		&(void *){0},
edb085
		&(void *){0},
edb085
		&(size_t){0},
edb085
		1);
edb085
}
edb085
edb085
edb085
int32_t __stdcall __ntapi_ipc_get_port_section_by_attr(
edb085
	__out	void **			hport,
edb085
	__in	nt_port_attr *		attr,
edb085
	__out	void **			hsection,
edb085
	__out	void **			section_addr,
edb085
	__out	size_t *		section_size)
edb085
{
edb085
	return __ipc_connect_by_attr(
edb085
		hport,attr,0,0,
edb085
		hsection,
edb085
		section_addr,
edb085
		section_size,
edb085
		1);
edb085
}
edb085
edb085
1b6aec
int32_t __stdcall __ntapi_ipc_init_section_by_port(
1b6aec
	__in	void *		hconn,
1b6aec
	__out	void **		hsection,
1b6aec
	__out	void **		secaddr,
1b6aec
	__out	size_t *	secsize)
1b6aec
{
1b6aec
	int32_t			status;
1b6aec
	nt_tty_section_info	secinfo;
1b6aec
	nt_iosb			iosb;
1b6aec
	struct dalist_node_ex *	node;
1b6aec
	nt_ipc_conn *		ipc;
1b6aec
	void *			addr;
1b6aec
	size_t			size;
1b6aec
	ntapi_internals *	__internals;
1b6aec
1b6aec
	/* init */
1b6aec
	__internals = __ntapi_internals();
1b6aec
1b6aec
	/* lock */
4e8398
        while (at_locked_cas(&__internals->hlock,0,1))
4e8398
		__ntapi->zw_delay_execution(
4e8398
			NT_SYNC_NON_ALERTABLE,
4e8398
			&(nt_timeout){{0,0}});
1b6aec
1b6aec
	/* connection node */
1b6aec
	if ((status = dalist_get_node_by_key(
1b6aec
			&__internals->ipc_conns,
1b6aec
			&node,(uintptr_t)hconn,
1b6aec
			DALIST_NODE_TYPE_EXISTING,
1b6aec
			&(uintptr_t){0})))
1b6aec
		return __ipc_connect_return(
1b6aec
			&__internals->hlock,
1b6aec
			NT_STATUS_INTERNAL_ERROR);
1b6aec
1b6aec
	else if (!node)
736fac
		return __ipc_connect_return(
736fac
			&__internals->hlock,
736fac
			NT_STATUS_NOT_FOUND);
1b6aec
1b6aec
	else
1b6aec
		ipc = (nt_ipc_conn *)&node->dblock;
1b6aec
1b6aec
	/* already mapped? */
1b6aec
	if (ipc->secaddr)
1b6aec
		return __ipc_connect_return(
1b6aec
			&__internals->hlock,
1b6aec
			NT_STATUS_SUCCESS);
1b6aec
1b6aec
	/* section info */
1b6aec
	if ((status = __ntapi->tty_query_information_section(
1b6aec
			hconn,&iosb,&secinfo,0)))
1b6aec
		return __ipc_connect_return(
1b6aec
			&__internals->hlock,
1b6aec
			status);
1b6aec
1b6aec
	/* map section */
1b6aec
	addr = 0;
1b6aec
	size = 0;
1b6aec
1b6aec
	if ((status = __ntapi->zw_map_view_of_section(
1b6aec
			secinfo.section,
1b6aec
			NT_CURRENT_PROCESS_HANDLE,
1b6aec
			&addr,0,
1b6aec
			secinfo.section_size,0,&size,
1b6aec
			NT_VIEW_UNMAP,0,
1b6aec
			NT_PAGE_READWRITE)))
1b6aec
		return __ipc_connect_return(
1b6aec
			&__internals->hlock,
1b6aec
			status);
1b6aec
1b6aec
	/* update */
1b6aec
	*hsection = secinfo.section;
1b6aec
	*secaddr  = addr;
1b6aec
	*secsize  = size;
1b6aec
1b6aec
	/* all done */
1b6aec
	return __ipc_connect_return(
1b6aec
		&__internals->hlock,
1b6aec
		NT_STATUS_SUCCESS);
1b6aec
}
1b6aec
1b6aec
1b6aec
int32_t __stdcall __ntapi_ipc_disconnect_unmap_section_by_port(
1b6aec
	__in	void *		hconn)
1b6aec
{
1b6aec
	int32_t			status;
1b6aec
	struct dalist_node_ex *	node;
1b6aec
	nt_ipc_conn *		ipc;
1b6aec
	ntapi_internals *	__internals;
1b6aec
1b6aec
	/* init */
1b6aec
	__internals = __ntapi_internals();
1b6aec
1b6aec
	/* lock */
f5ce7c
        while (at_locked_cas(&__internals->hlock,0,1))
f5ce7c
		__ntapi->zw_delay_execution(
f5ce7c
			NT_SYNC_NON_ALERTABLE,
f5ce7c
			&(nt_timeout){{0,0}});
1b6aec
1b6aec
	/* connection node */
1b6aec
	if ((status = dalist_get_node_by_key(
1b6aec
			&__internals->ipc_conns,
1b6aec
			&node,(uintptr_t)hconn,
1b6aec
			DALIST_NODE_TYPE_EXISTING,
1b6aec
			&(uintptr_t){0})))
1b6aec
		return __ipc_connect_return(
1b6aec
			&__internals->hlock,
1b6aec
			NT_STATUS_INTERNAL_ERROR);
1b6aec
1b6aec
	else if (!node)
1b6aec
		return __ipc_connect_return(
1b6aec
			&__internals->hlock,
1b6aec
			NT_STATUS_NOT_FOUND);
1b6aec
1b6aec
	else
1b6aec
		ipc = (nt_ipc_conn *)&node->dblock;
1b6aec
1b6aec
	/* unmap section */
1b6aec
	if (ipc->secaddr)
1b6aec
		__ntapi->zw_unmap_view_of_section(
1b6aec
			NT_CURRENT_PROCESS_HANDLE,
1b6aec
			ipc->secaddr);
1b6aec
1b6aec
	/* close section */
1b6aec
	if (ipc->hsection)
1b6aec
		__ntapi->zw_close(ipc->hsection);
1b6aec
1b6aec
	/* disconnect */
1b6aec
	__ntapi->zw_close(hconn);
1b6aec
1b6aec
	/* remove node */
1b6aec
	dalist_discard_node(&__internals->ipc_conns,node);
1b6aec
1b6aec
	return __ipc_connect_return(
1b6aec
		&__internals->hlock,
1b6aec
		NT_STATUS_SUCCESS);
1b6aec
}