Blame src/pty/ntapi_pty_fd.c

dd89bb
/********************************************************/
dd89bb
/*  ntapi: Native API core library                      */
4256e2
/*  Copyright (C) 2013--2016  Z. Gilboa                 */
dd89bb
/*  Released under GPLv2 and GPLv3; see COPYING.NTAPI.  */
dd89bb
/********************************************************/
dd89bb
dd89bb
#include <psxtypes/psxtypes.h>
dd89bb
#include <ntapi/nt_port.h>
dd89bb
#include <ntapi/nt_tty.h>
dd89bb
#include <ntapi/ntapi.h>
dd89bb
#include "ntapi_impl.h"
dd89bb
#include "ntapi_pty.h"
dd89bb
dd89bb
static int32_t __stdcall __ntapi_pty_open_close(
dd89bb
	nt_pty *	pty,
dd89bb
	nt_iosb *	iosb,
dd89bb
	int32_t		opcode)
dd89bb
{
dd89bb
	int32_t		status;
dd89bb
	nt_pty_fd_msg	msg;
dd89bb
dd89bb
	__ntapi->tt_aligned_block_memset(&msg,0,sizeof(msg));
dd89bb
dd89bb
	msg.header.msg_type	= NT_LPC_NEW_MESSAGE;
dd89bb
	msg.header.data_size	= sizeof(msg.data);
dd89bb
	msg.header.msg_size	= sizeof(msg);
dd89bb
	msg.data.ttyinfo.opcode	= opcode;
dd89bb
dd89bb
	msg.data.fdinfo.hpty	= pty->hpty;
dd89bb
	msg.data.fdinfo.access	= pty->access;
dd89bb
	msg.data.fdinfo.flags	= pty->flags;
dd89bb
	msg.data.fdinfo.share	= pty->share;
dd89bb
	msg.data.fdinfo.options	= pty->options;
dd89bb
dd89bb
	msg.data.fdinfo.luid.high = pty->luid.high;
dd89bb
	msg.data.fdinfo.luid.low  = pty->luid.low;
dd89bb
dd89bb
	__ntapi_tt_guid_copy(
dd89bb
		&msg.data.fdinfo.guid,
dd89bb
		&pty->guid);
dd89bb
dd89bb
	if ((status = __ntapi->zw_request_wait_reply_port(pty->hport,&msg,&msg)))
dd89bb
		return status;
dd89bb
	else if (msg.data.ttyinfo.status)
dd89bb
		return msg.data.ttyinfo.status;
dd89bb
dd89bb
	pty->hpty	  = msg.data.fdinfo.hpty;
dd89bb
	pty->section	  = msg.data.fdinfo.section;
dd89bb
	pty->section_size = msg.data.fdinfo.section_size;
dd89bb
	pty->luid.high	  = msg.data.fdinfo.luid.high;
dd89bb
	pty->luid.low	  = msg.data.fdinfo.luid.low;
dd89bb
	iosb->status	  = msg.data.ttyinfo.status;
dd89bb
	iosb->info	  = 0;
dd89bb
dd89bb
	return NT_STATUS_SUCCESS;
dd89bb
}
dd89bb
dd89bb
dd89bb
static int32_t __fastcall __ntapi_pty_free(nt_pty * pty)
dd89bb
{
dd89bb
	void *	addr;
dd89bb
	size_t	size;
dd89bb
dd89bb
	/* unmap section */
dd89bb
	if (pty->section_addr)
dd89bb
		__ntapi->zw_unmap_view_of_section(
dd89bb
			NT_CURRENT_PROCESS_HANDLE,
dd89bb
			pty->section_addr);
dd89bb
dd89bb
	/* free control block */
dd89bb
	addr = pty->addr;
dd89bb
	size = pty->size;
dd89bb
dd89bb
	return __ntapi->zw_free_virtual_memory(
dd89bb
		NT_CURRENT_PROCESS_HANDLE,
dd89bb
		&addr,
dd89bb
		&size,
dd89bb
		NT_MEM_RELEASE);
dd89bb
}
dd89bb
dd89bb
dd89bb
static int32_t __fastcall __ntapi_pty_fail(nt_pty * pty,int32_t status)
dd89bb
{
dd89bb
	__ntapi_pty_free(pty);
dd89bb
	return status;
dd89bb
}
dd89bb
dd89bb
dd89bb
static int32_t __fastcall __ntapi_pty_alloc(nt_pty ** pty)
dd89bb
{
dd89bb
	int32_t		status;
dd89bb
	nt_pty *	ctx;
dd89bb
	size_t		ctx_size;
dd89bb
dd89bb
	/* allocate control block */
dd89bb
	ctx = 0;
dd89bb
	ctx_size = sizeof(nt_pty);
dd89bb
dd89bb
	if ((status = __ntapi->zw_allocate_virtual_memory(
dd89bb
			NT_CURRENT_PROCESS_HANDLE,
dd89bb
			(void **)&ctx,
dd89bb
			0,&ctx_size,
dd89bb
			NT_MEM_COMMIT,
dd89bb
			NT_PAGE_READWRITE)))
dd89bb
		return status;
dd89bb
dd89bb
	/* init control block */
dd89bb
	__ntapi->tt_aligned_block_memset(
dd89bb
		ctx,0,ctx_size);
dd89bb
dd89bb
	ctx->addr = ctx;
dd89bb
	ctx->size = ctx_size;
dd89bb
dd89bb
	*pty = ctx;
dd89bb
	return NT_STATUS_SUCCESS;
dd89bb
}
dd89bb
dd89bb
static int32_t __ntapi_pty_connect(
dd89bb
	void *		hport,
dd89bb
	nt_pty *	ctx,
dd89bb
	nt_iosb *	iosb)
dd89bb
{
dd89bb
	int32_t status;
dd89bb
dd89bb
	ctx->hport = hport
dd89bb
		? hport
dd89bb
		: __ntapi_internals()->hport_tty_session;
dd89bb
dd89bb
	/* request */
dd89bb
	iosb = iosb ? iosb : &ctx->iosb;
dd89bb
dd89bb
	if ((status = __ntapi_pty_open_close(ctx,iosb,NT_TTY_PTY_OPEN)))
dd89bb
		return __ntapi_pty_fail(ctx,status);
dd89bb
dd89bb
	/* map section */
dd89bb
	if ((status = __ntapi->zw_map_view_of_section(
dd89bb
			ctx->section,
dd89bb
			NT_CURRENT_PROCESS_HANDLE,
dd89bb
			&ctx->section_addr,
dd89bb
			0,ctx->section_size,
dd89bb
			0,&ctx->section_size,
dd89bb
			NT_VIEW_UNMAP,0,
dd89bb
			NT_PAGE_READWRITE)))
dd89bb
		return __ntapi_pty_fail(ctx,status);
dd89bb
dd89bb
	/* assume conforming clients, config for single lock try */
dd89bb
	__ntapi->tt_sync_block_init(&ctx->sync[__PTY_READ],0,0,1,0,0);
dd89bb
	__ntapi->tt_sync_block_init(&ctx->sync[__PTY_WRITE],0,0,1,0,0);
dd89bb
dd89bb
	return NT_STATUS_SUCCESS;
dd89bb
}
dd89bb
dd89bb
dd89bb
int32_t	__stdcall __ntapi_pty_open(
dd89bb
	void *			hport,
dd89bb
	nt_pty **		pty,
dd89bb
	uint32_t		desired_access,
dd89bb
	nt_object_attributes*	obj_attr,
dd89bb
	nt_iosb *		iosb,
dd89bb
	uint32_t		share_access,
dd89bb
	uint32_t		open_options)
dd89bb
{
dd89bb
	int32_t			status;
dd89bb
	uint32_t		hash;
dd89bb
	nt_guid			guid;
dd89bb
	nt_uuid_str_utf16 *	guid_str;
dd89bb
	nt_pty *		ctx;
dd89bb
dd89bb
	if (!obj_attr || !obj_attr->obj_name || !obj_attr->obj_name->buffer)
dd89bb
		return NT_STATUS_INVALID_PARAMETER;
dd89bb
dd89bb
	if (obj_attr->obj_name->strlen != __DEVICE_PATH_PREFIX_LEN + sizeof(nt_guid_str_utf16))
dd89bb
		return NT_STATUS_OBJECT_PATH_INVALID;
dd89bb
dd89bb
	hash = __ntapi->tt_buffer_crc32(
dd89bb
		0,
dd89bb
		obj_attr->obj_name->buffer,
dd89bb
		__DEVICE_PATH_PREFIX_LEN);
dd89bb
dd89bb
	if (hash != __DEVICE_PATH_PREFIX_HASH)
dd89bb
		return NT_STATUS_OBJECT_PATH_INVALID;
dd89bb
dd89bb
	guid_str = (nt_uuid_str_utf16 *)
dd89bb
		((uintptr_t)obj_attr->obj_name->buffer + __DEVICE_PATH_PREFIX_LEN);
dd89bb
dd89bb
	if (__ntapi->tt_utf16_string_to_guid(guid_str,&guid))
dd89bb
		return NT_STATUS_OBJECT_NAME_INVALID;
dd89bb
dd89bb
	/* control block */
dd89bb
	if ((status = __ntapi_pty_alloc(&ctx)))
dd89bb
		return status;
dd89bb
dd89bb
	__ntapi_tt_guid_copy(
dd89bb
		&ctx->guid,
dd89bb
		&guid);
dd89bb
dd89bb
	ctx->access	= desired_access;
dd89bb
	ctx->flags	= obj_attr->obj_attr;
dd89bb
	ctx->share	= share_access;
dd89bb
	ctx->options	= open_options;
dd89bb
dd89bb
	/* pts */
dd89bb
	if (obj_attr->root_dir) {
dd89bb
		ctx->luid.high = ((nt_pty *)obj_attr->root_dir)->luid.high;
dd89bb
		ctx->luid.low  = ((nt_pty *)obj_attr->root_dir)->luid.low;
dd89bb
	}
dd89bb
dd89bb
	if ((status = __ntapi_pty_connect(hport,ctx,iosb)))
dd89bb
		return status;
dd89bb
dd89bb
	*pty = ctx;
dd89bb
dd89bb
	return NT_STATUS_SUCCESS;
dd89bb
}
dd89bb
efc01e
int32_t	__stdcall __ntapi_pty_inherit(
efc01e
	__in	void *			hport,
efc01e
	__out	nt_pty **		pty,
efc01e
	__in 	nt_pty_client_info * 	client_info)
efc01e
{
efc01e
	int32_t 		status;
efc01e
	nt_iosb 		iosb;
efc01e
	nt_pty_inherit_info 	inherit;
efc01e
	nt_pty *		ctx;
efc01e
efc01e
	inherit.any[0] = client_info->any[0];
efc01e
	inherit.any[1] = client_info->any[1];
efc01e
	inherit.any[2] = client_info->any[2];
efc01e
	inherit.any[3] = client_info->any[3];
efc01e
efc01e
	if ((status = __ntapi_pty_query(
efc01e
			hport,&iosb,
efc01e
			&inherit,sizeof(inherit),
efc01e
			NT_PTY_INHERIT_INFORMATION)))
efc01e
		return status;
efc01e
efc01e
	/* control block */
efc01e
	if ((status = __ntapi_pty_alloc(&ctx)))
efc01e
		return status;
efc01e
efc01e
	__ntapi_tt_guid_copy(
efc01e
		&ctx->guid,
efc01e
		&inherit.guid);
efc01e
efc01e
	ctx->access	= inherit.access;
efc01e
	ctx->flags	= inherit.flags;
efc01e
	ctx->share	= inherit.share;
efc01e
	ctx->options	= inherit.options;
efc01e
efc01e
	ctx->luid.low 	= inherit.luid.low;
efc01e
	ctx->luid.high 	= inherit.luid.high;
efc01e
efc01e
	if ((status = __ntapi_pty_connect(hport,ctx,&iosb)))
efc01e
		return status;
efc01e
efc01e
	*pty = ctx;
efc01e
efc01e
	return NT_STATUS_SUCCESS;
efc01e
}
efc01e
dd89bb
int32_t	__stdcall __ntapi_pty_reopen(
dd89bb
	__in	void *			hport,
dd89bb
	__in	nt_pty *		pty)
dd89bb
{
dd89bb
	return __ntapi_pty_connect(hport,pty,0);
dd89bb
}
dd89bb
dd89bb
int32_t __stdcall __ntapi_pty_close(nt_pty * pty)
dd89bb
{
dd89bb
	if (!pty || (pty->addr != pty))
dd89bb
		return NT_STATUS_INVALID_PARAMETER;
dd89bb
dd89bb
	__ntapi_pty_open_close(
dd89bb
		pty,&pty->iosb,NT_TTY_PTY_CLOSE);
dd89bb
dd89bb
	return __ntapi_pty_free(pty);
dd89bb
}