Blame src/tty/ntapi_tty_create_session.c

dd89bb
/********************************************************/
dd89bb
/*  ntapi: Native API core library                      */
dde53a
/*  Copyright (C) 2013--2017  Z. Gilboa                 */
dd89bb
/*  Released under GPLv2 and GPLv3; see COPYING.NTAPI.  */
dd89bb
/********************************************************/
dd89bb
dd89bb
#include <psxtypes/psxtypes.h>
dd89bb
#include <ntapi/ntapi.h>
dd89bb
#include "ntapi_impl.h"
dd89bb
dd89bb
static int32_t __fastcall __tty_create_session_return(
0d309b
	void *				hready,
dd89bb
	nt_create_process_params *	params,
dd89bb
	int32_t				status)
dd89bb
{
0d309b
	if (params->hprocess && status)
dd89bb
		__ntapi->zw_terminate_process(
dd89bb
			params->hprocess,
dd89bb
			NT_STATUS_UNEXPECTED_IO_ERROR);
dd89bb
0d309b
	__ntapi->zw_close(hready);
dd89bb
	__ntapi->zw_close(params->hprocess);
dd89bb
	__ntapi->zw_close(params->hthread);
dd89bb
dd89bb
	return status;
dd89bb
}
dd89bb
dd89bb
int32_t __stdcall __ntapi_tty_create_session(
dd89bb
	__out	void **			hport,
dd89bb
	__out	nt_port_name *		port_name,
dd89bb
	__in	nt_tty_session_type	type,
e3e5a2
	__in	nt_tty_session_subtype	subtype,
dd89bb
	__in	const nt_guid *		guid		__optional,
1f883a
	__in	wchar16_t *		image_name,
f61917
	__in	void *			htty		__optional)
dd89bb
{
dd89bb
	nt_status			status;
dd89bb
	ntapi_internals *		__internals;
f61917
	void *				shport;
f61917
	nt_port_name			sport_name;
f61917
	nt_tty_server_basic_info	ttyinfo;
f61917
	nt_iosb				iosb;
dd89bb
dd89bb
	nt_port_attr			port_attr;
df0e42
	nt_runtime_data *		rtdata;
dd89bb
	nt_runtime_data			ssattr;
dd89bb
	nt_runtime_data_block		rtblock;
dd89bb
	nt_create_process_params	params;
abc6f7
	nt_event_basic_information	eready;
dd89bb
b58b75
	/* abi/api */
b58b75
	(void)subtype;
b58b75
1f883a
	/* validate */
1f883a
	if (!image_name)
1f883a
		return NT_STATUS_INVALID_PARAMETER;
dd89bb
dd89bb
	/* init */
dd89bb
	__internals = __ntapi_internals();
df0e42
	rtdata      = __internals->rtdata;
dd89bb
dd89bb
	__ntapi->tt_aligned_block_memset(
dd89bb
		&port_attr,0,sizeof(port_attr));
dd89bb
f61917
	__ntapi->tt_aligned_block_memset(
f61917
		&ssattr,0,sizeof(ssattr));
f61917
171c2d
	/* port type */
171c2d
	if (guid) {
171c2d
		if ((status = __ntapi->tt_port_type_from_guid(
171c2d
				&port_attr.type,
171c2d
				&port_attr.subtype,
171c2d
				guid)))
171c2d
			return status;
171c2d
	} else {
171c2d
		port_attr.type = NT_PORT_TYPE_SUBSYSTEM;
171c2d
	}
171c2d
171c2d
	/* port subtype */
dd89bb
	switch (type) {
dd89bb
		case NT_TTY_SESSION_PRIMARY:
dd89bb
			port_attr.subtype = NT_PORT_SUBTYPE_DEFAULT;
dd89bb
dd89bb
			if (!hport)
dd89bb
				hport = &__internals->hport_tty_session;
dd89bb
dd89bb
			if (!port_name)
dd89bb
				port_name = __internals->subsystem;
dd89bb
dd89bb
			break;
dd89bb
f61917
		case NT_TTY_SESSION_SECONDARY:
f61917
			port_attr.subtype = NT_PORT_SUBTYPE_DEFAULT;
f61917
f61917
			if (!hport)
f61917
				hport = &shport;
f61917
f61917
			if (!port_name)
f61917
				port_name = &sport_name;
f61917
f61917
			break;
f61917
dd89bb
		case NT_TTY_SESSION_PRIVATE:
dd89bb
			port_attr.subtype = NT_PORT_SUBTYPE_PRIVATE;
dd89bb
			break;
dd89bb
dd89bb
		default:
dd89bb
			return NT_STATUS_INVALID_PARAMETER;
dd89bb
	}
dd89bb
dd89bb
	/* port guid */
dd89bb
	if (guid)
dd89bb
		__ntapi->tt_guid_copy(
dd89bb
			&port_attr.guid,
dd89bb
			guid);
dd89bb
	else
dd89bb
		__ntapi->tt_port_guid_from_type(
dd89bb
			&port_attr.guid,
dd89bb
			port_attr.type,
dd89bb
			port_attr.subtype);
dd89bb
dd89bb
	/* port keys */
dd89bb
	if ((status = __ntapi->tt_port_generate_keys(&port_attr.keys)))
dd89bb
		return status;
dd89bb
dd89bb
	/* port name */
6d5726
	__ntapi->tt_port_name_from_attr(
dd89bb
		port_name,
dd89bb
		&port_attr);
dd89bb
f61917
	/* parent session) */
f61917
	if (htty && (htty != NT_INVALID_HANDLE_VALUE)) {
f61917
		if ((status = __ntapi->tty_query_information_server(
f61917
				htty,&iosb,
f61917
				&ttyinfo,sizeof(ttyinfo),
f61917
				NT_TTY_SERVER_BASIC_INFORMATION)))
f61917
			return status;
dd89bb
f61917
		ssattr.tty_type		= ttyinfo.attr.type;
f61917
		ssattr.tty_subtype	= ttyinfo.attr.subtype;
f61917
f61917
		ssattr.tty_keys[0]	= ttyinfo.attr.keys.key[0];
f61917
		ssattr.tty_keys[1]	= ttyinfo.attr.keys.key[1];
f61917
		ssattr.tty_keys[2]	= ttyinfo.attr.keys.key[2];
f61917
		ssattr.tty_keys[3]	= ttyinfo.attr.keys.key[3];
f61917
		ssattr.tty_keys[4]	= ttyinfo.attr.keys.key[4];
f61917
		ssattr.tty_keys[5]	= ttyinfo.attr.keys.key[5];
f61917
f61917
		__ntapi->tt_guid_copy(
f61917
			&ssattr.tty_guid,
f61917
			&ttyinfo.attr.guid);
f61917
	}
f61917
f61917
	/* subsystem attributes */
e3a284
	__ntapi->tt_guid_copy(
e3a284
		&ssattr.abi,
e3a284
		&(nt_guid)NT_PROCESS_GUID_RTDATA);
e3a284
b58b75
	ssattr.srv_type		= port_attr.type;
b58b75
	ssattr.srv_subtype	= port_attr.subtype;
e3e5a2
dd89bb
	ssattr.srv_keys[0]	= port_attr.keys.key[0];
dd89bb
	ssattr.srv_keys[1]	= port_attr.keys.key[1];
dd89bb
	ssattr.srv_keys[2]	= port_attr.keys.key[2];
dd89bb
	ssattr.srv_keys[3]	= port_attr.keys.key[3];
dd89bb
	ssattr.srv_keys[4]	= port_attr.keys.key[4];
dd89bb
	ssattr.srv_keys[5]	= port_attr.keys.key[5];
dd89bb
dd89bb
	__ntapi->tt_guid_copy(
dd89bb
		&ssattr.srv_guid,
dd89bb
		&port_attr.guid);
dd89bb
dd89bb
	if ((status = __ntapi->tt_create_private_event(
6336c4
			&ssattr.hserver,
6c2850
			NT_NOTIFICATION_EVENT,
dd89bb
			NT_EVENT_NOT_SIGNALED)))
dd89bb
		return status;
dd89bb
df0e42
	/* server chain */
df0e42
	if (rtdata->srv_type) {
df0e42
		ssattr.ppid_type	= rtdata->srv_type;
df0e42
		ssattr.ppid_subtype	= rtdata->srv_subtype;
df0e42
df0e42
		ssattr.ppid_keys[0]	= rtdata->srv_keys[0];
df0e42
		ssattr.ppid_keys[1]	= rtdata->srv_keys[1];
df0e42
		ssattr.ppid_keys[2]	= rtdata->srv_keys[2];
df0e42
		ssattr.ppid_keys[3]	= rtdata->srv_keys[3];
df0e42
		ssattr.ppid_keys[4]	= rtdata->srv_keys[4];
df0e42
		ssattr.ppid_keys[5]	= rtdata->srv_keys[5];
df0e42
df0e42
		__ntapi->tt_guid_copy(
df0e42
			&ssattr.ppid_guid,
df0e42
			&rtdata->srv_guid);
df0e42
	}
df0e42
dd89bb
	/* create subsystem process */
dd89bb
	rtblock.addr		= &ssattr;
dd89bb
	rtblock.size		= sizeof(ssattr);
dd89bb
	rtblock.remote_addr	= 0;
dd89bb
	rtblock.remote_size	= 0;
dd89bb
	rtblock.flags		= NT_RUNTIME_DATA_DUPLICATE_SESSION_HANDLES;
dd89bb
dd89bb
	__ntapi->tt_aligned_block_memset(
dd89bb
		&params,0,sizeof(params));
dd89bb
dd89bb
	params.image_name	= image_name;
dd89bb
	params.rtblock		= &rtblock;
f61917
	params.hsession		= htty;
dd89bb
dd89bb
	if ((status = __ntapi->tt_create_native_process(&params)))
6336c4
		return __tty_create_session_return(ssattr.hserver,&params,status);
dd89bb
abc6f7
	__ntapi->zw_wait_for_multiple_objects(
abc6f7
		2,
6336c4
		(void *[]){ssattr.hserver,params.hprocess},
abc6f7
		NT_WAIT_ANY,
abc6f7
		NT_SYNC_NON_ALERTABLE,
abc6f7
		0);
abc6f7
abc6f7
	if ((status = __ntapi->zw_query_event(
6336c4
			ssattr.hserver,
abc6f7
			NT_EVENT_BASIC_INFORMATION,
abc6f7
			&eready,
abc6f7
			sizeof(eready),
abc6f7
			&(size_t){0})))
6336c4
		return __tty_create_session_return(ssattr.hserver,&params,status);
dd89bb
abc6f7
	if (!eready.signal_state)
6336c4
		return __tty_create_session_return(ssattr.hserver,&params,NT_STATUS_SYSTEM_PROCESS_TERMINATED);
abc6f7
dd89bb
	/* connect to subsystem */
dd89bb
	if ((status = __ntapi->tty_connect(
dd89bb
			hport,
dd89bb
			&port_name->base_named_objects[0],
dd89bb
			NT_SECURITY_IMPERSONATION)))
6336c4
		return __tty_create_session_return(ssattr.hserver,&params,status);
dd89bb
dd89bb
	/* finalize primary session */
dd89bb
	if (type == NT_TTY_SESSION_PRIMARY) {
dd89bb
		if (hport != &__internals->hport_tty_session)
dd89bb
			__internals->hport_tty_session = *hport;
dd89bb
dd89bb
		if (port_name != __internals->subsystem)
dd89bb
			__ntapi->tt_memcpy_utf16(
dd89bb
				__internals->subsystem->base_named_objects,
dd89bb
				port_name->base_named_objects,
dd89bb
				sizeof(*port_name));
dd89bb
	};
dd89bb
6336c4
	return __tty_create_session_return(ssattr.hserver,&params,NT_STATUS_SUCCESS);
dd89bb
}