Blame src/pty/ptyc_spawn.c

9cd8e5
/*********************************************************/
9cd8e5
/*  ptycon: a pty-console bridge                         */
9cd8e5
/*  Copyright (C) 2016  Z. Gilboa                        */
9cd8e5
/*  Released under GPLv2 and GPLv3; see COPYING.PTYCON.  */
9cd8e5
/*********************************************************/
9cd8e5
9cd8e5
#include <psxtypes/psxtypes.h>
9cd8e5
#include <ntcon/ntcon.h>
9cd8e5
#include <ntapi/ntapi.h>
9cd8e5
9cd8e5
#include <ptycon/ptycon.h>
9cd8e5
#include "ptycon_driver_impl.h"
9cd8e5
9cd8e5
static int32_t __stdcall ptyc_spawn_return(
9cd8e5
	nt_runtime_data_block *	rtblock,
9cd8e5
	int32_t			status)
9cd8e5
{
9cd8e5
	nt_runtime_data *	rtdata;
9cd8e5
9cd8e5
	rtdata = (nt_runtime_data *)rtblock;
9cd8e5
9cd8e5
	if (rtdata->hready)
9cd8e5
		ntapi->zw_close(
9cd8e5
			rtdata->hready);
9cd8e5
9cd8e5
	ntapi->zw_free_virtual_memory(
9cd8e5
		NT_CURRENT_PROCESS_HANDLE,
9cd8e5
		&rtblock->addr,
9cd8e5
		&rtblock->size,
9cd8e5
		NT_MEM_RELEASE);
9cd8e5
9cd8e5
	return status;
9cd8e5
}
9cd8e5
9cd8e5
int __stdcall ptyc_spawn(struct ptyc_driver_ctx * dctx)
9cd8e5
{
9cd8e5
	int32_t				status;
9cd8e5
	char *				patharg;
9cd8e5
	void *				hchild[2];
9cd8e5
	nt_create_process_params	params;
9cd8e5
	struct ptyc_driver_ctx_impl *	ictx;
9cd8e5
	struct ptyc_client_ctx *	clctx;
9cd8e5
	nt_tty_session_info		session;
9cd8e5
	nt_runtime_data_block		rtblock;
9cd8e5
	nt_runtime_data *		rdata;
9cd8e5
	nt_rtdata *			self;
9cd8e5
	nt_peb * 			peb;
9cd8e5
	void *				hat;
9cd8e5
	void *				hfile;
9cd8e5
	char **				rargv;
9cd8e5
	char **				renvp;
9cd8e5
	wchar16_t **			pwarg;
9cd8e5
	wchar16_t *			wch;
9cd8e5
	nt_unicode_string *		imgname;
9cd8e5
	uint32_t			written;
9cd8e5
	uintptr_t			imgbuf[8192/sizeof(uintptr_t)];
9cd8e5
9cd8e5
	/* init */
9cd8e5
	if (!(ictx = ptyc_get_driver_ictx(dctx)))
9cd8e5
		return NT_STATUS_INVALID_HANDLE;
9cd8e5
9cd8e5
	if (!dctx->cctx->eargv)
9cd8e5
		return NT_STATUS_SUCCESS;
9cd8e5
9cd8e5
	if ((status = ntapi->tt_get_runtime_data(&self,0)))
9cd8e5
		return status;
9cd8e5
9cd8e5
	clctx = &ictx->clctx;
9cd8e5
9cd8e5
	/* hat */
9cd8e5
	if (!(peb = (nt_peb *)pe_get_peb_address()))
9cd8e5
		return NT_STATUS_INTERNAL_ERROR;
9cd8e5
9cd8e5
	if (!peb->process_params)
9cd8e5
		return NT_STATUS_INTERNAL_ERROR;
9cd8e5
9cd8e5
	hat = (dctx->cctx->hroot && (dctx->cctx->eargv[0][0] == '/'))
9cd8e5
		? dctx->cctx->hroot
9cd8e5
		: self->hcwd
9cd8e5
			? self->hcwd
9cd8e5
			: peb->process_params->cwd_handle;
9cd8e5
9cd8e5
	patharg = (dctx->cctx->eargv[0][0] == '/')
9cd8e5
		? &dctx->cctx->eargv[0][1]
9cd8e5
		: &dctx->cctx->eargv[0][0];
9cd8e5
9cd8e5
	/* hfile */
9cd8e5
	if ((status = ptyc_open_file(&hfile,hat,patharg,true)))
9cd8e5
		return status;
9cd8e5
9cd8e5
	/* rtblock */
9cd8e5
	rtblock.addr		= 0;
9cd8e5
	rtblock.size		= 0x10000;
9cd8e5
	rtblock.remote_addr	= 0;
9cd8e5
	rtblock.remote_size	= 0;
9cd8e5
	rtblock.flags		= 0;
9cd8e5
9cd8e5
	if ((status = ntapi->zw_allocate_virtual_memory(
9cd8e5
			self->hprocess_self,
9cd8e5
			&rtblock.addr,0,
9cd8e5
			&rtblock.size,
9cd8e5
			NT_MEM_COMMIT,
9cd8e5
			NT_PAGE_READWRITE)))
9cd8e5
		return status;
9cd8e5
9cd8e5
	ntapi->tt_aligned_block_memset(
9cd8e5
		rtblock.addr,0,rtblock.size);
9cd8e5
9cd8e5
	if ((status = ntapi->zw_query_object(
9cd8e5
			hfile,
9cd8e5
			NT_OBJECT_NAME_INFORMATION,
9cd8e5
			imgbuf,sizeof(imgbuf),
9cd8e5
			&written)))
9cd8e5
		return ptyc_spawn_return(
9cd8e5
			&rtblock,status);
9cd8e5
9cd8e5
	imgname = (nt_unicode_string *)imgbuf;
9cd8e5
	rdata   = (nt_runtime_data *)rtblock.addr;
9cd8e5
9cd8e5
	/* argv, envp */
9cd8e5
	if ((status = ntapi->tt_array_copy_utf8(
9cd8e5
			&rdata->argc,
9cd8e5
			(const char **)dctx->cctx->eargv,
9cd8e5
			(const char **)self->envp,
9cd8e5
			0,0,0,
9cd8e5
			rtblock.addr,
9cd8e5
			rdata->buffer,
9cd8e5
			rtblock.size - sizeof(*rdata),
9cd8e5
			&rtblock.remote_size)))
9cd8e5
		return ptyc_spawn_return(
9cd8e5
			&rtblock,status);
9cd8e5
9cd8e5
	rdata->argv = (char **)&((nt_runtime_data *)0)->buffer;
9cd8e5
	rdata->envp = rdata->argv + rdata->argc + 1;
9cd8e5
9cd8e5
	rdata->wargv = (wchar16_t **)(rdata->buffer + (rtblock.remote_size / sizeof(uintptr_t)) + 1);
9cd8e5
	rdata->wenvp = rdata->wargv + rdata->argc + 1;
9cd8e5
9cd8e5
	rargv = rdata->argv + ((uintptr_t)rtblock.addr / sizeof(char *));
9cd8e5
	renvp = rdata->envp + ((uintptr_t)rtblock.addr / sizeof(char *));
9cd8e5
9cd8e5
	pwarg = rdata->wenvp + self->envc + 1;
9cd8e5
	wch = (wchar16_t *)pwarg;
9cd8e5
9cd8e5
	if ((status = ntapi->tt_array_convert_utf8_to_utf16(
9cd8e5
			rargv,
9cd8e5
			rdata->wargv,
9cd8e5
			rdata,
9cd8e5
			wch,
9cd8e5
			rtblock.size - sizeof(wchar16_t)*(wch-(wchar16_t *)rdata->buffer),
9cd8e5
			&rtblock.remote_size)))
9cd8e5
		return ptyc_spawn_return(
9cd8e5
			&rtblock,status);
9cd8e5
9cd8e5
	wch += rtblock.remote_size/sizeof(wchar16_t);
9cd8e5
9cd8e5
	if ((status = ntapi->tt_array_convert_utf8_to_utf16(
9cd8e5
			renvp,
9cd8e5
			rdata->wenvp,
9cd8e5
			rdata,
9cd8e5
			wch,
9cd8e5
			rtblock.size - sizeof(wchar16_t)*(wch-(wchar16_t *)rdata->buffer),
9cd8e5
			&rtblock.remote_size)))
9cd8e5
		return ptyc_spawn_return(
9cd8e5
			&rtblock,status);
9cd8e5
9cd8e5
	rdata->wargv -= (uintptr_t)rtblock.addr / sizeof(wchar16_t *);
9cd8e5
	rdata->wenvp -= (uintptr_t)rtblock.addr / sizeof(wchar16_t *);
9cd8e5
9cd8e5
	/* session */
9cd8e5
	if ((status = ntapi->tt_create_inheritable_event(
9cd8e5
			&rdata->hready,
9cd8e5
			NT_NOTIFICATION_EVENT,
9cd8e5
			NT_EVENT_NOT_SIGNALED)))
9cd8e5
		return ptyc_spawn_return(
9cd8e5
			&rtblock,status);
9cd8e5
9cd8e5
	ntapi->tt_aligned_block_memcpy(
9cd8e5
		(uintptr_t *)&rdata->cid_parent,
9cd8e5
		(uintptr_t *)&self->cid_self,
9cd8e5
		sizeof(nt_cid));
9cd8e5
9cd8e5
	rdata->hroot = dctx->cctx->hroot;
9cd8e5
	rdata->hcwd  = self->hcwd
9cd8e5
			? self->hcwd
9cd8e5
			: peb->process_params->cwd_handle;
9cd8e5
9cd8e5
	rdata->srv_keys[0] = self->srv_keys[0];
9cd8e5
	rdata->srv_keys[1] = self->srv_keys[1];
9cd8e5
	rdata->srv_keys[2] = self->srv_keys[2];
9cd8e5
	rdata->srv_keys[3] = self->srv_keys[3];
9cd8e5
	rdata->srv_keys[4] = self->srv_keys[4];
9cd8e5
	rdata->srv_keys[5] = self->srv_keys[5];
9cd8e5
9cd8e5
	rdata->hstdin      = NT_INVALID_HANDLE_VALUE;
9cd8e5
	rdata->hstdout     = NT_INVALID_HANDLE_VALUE;
9cd8e5
	rdata->hstderr     = NT_INVALID_HANDLE_VALUE;
9cd8e5
9cd8e5
	rdata->stdin_type  = NT_FILE_TYPE_PTY;
9cd8e5
	rdata->stdout_type = NT_FILE_TYPE_PTY;
9cd8e5
	rdata->stderr_type = NT_FILE_TYPE_PTY;
9cd8e5
9cd8e5
	rdata->ptyany[0]   = clctx->clinfo.any[0];
9cd8e5
	rdata->ptyany[1]   = clctx->clinfo.any[1];
9cd8e5
	rdata->ptyany[2]   = clctx->clinfo.any[2];
9cd8e5
	rdata->ptyany[3]   = clctx->clinfo.any[3];
9cd8e5
9cd8e5
	/* params */
9cd8e5
	ntapi->tt_aligned_block_memset(
9cd8e5
		&params,0,sizeof(params));
9cd8e5
9cd8e5
	params.image_name		= imgname->buffer;
9cd8e5
	params.rtblock			= &rtblock;
9cd8e5
	params.creation_flags_process	= NT_PROCESS_CREATE_FLAGS_INHERIT_HANDLES;
9cd8e5
	params.creation_flags_thread	= NT_PROCESS_CREATE_FLAGS_CREATE_THREAD_SUSPENDED;
9cd8e5
9cd8e5
	/* hoppla */
9cd8e5
	if ((status = ntapi->tt_create_native_process(&params)))
9cd8e5
		return ptyc_spawn_return(
9cd8e5
			&rtblock,status);
9cd8e5
9cd8e5
	/* clctx */
9cd8e5
	clctx->hprocess		= params.hprocess;
9cd8e5
	clctx->hthread		= params.hthread;
9cd8e5
	clctx->cid.process_id	= params.cid.process_id;
9cd8e5
	clctx->cid.thread_id	= params.cid.thread_id;
9cd8e5
9cd8e5
	if ((status = ntapi->tty_client_process_register(
9cd8e5
			self->hsession,
9cd8e5
			params.pbi.unique_process_id,
9cd8e5
			0,NT_TTY_INHERIT_HANDLES,0)))
9cd8e5
		ntapi->zw_terminate_process(
9cd8e5
			params.hprocess,
9cd8e5
			status);
9cd8e5
9cd8e5
	session.pid    = 0;
9cd8e5
	session.pgid   = 0;
9cd8e5
	session.sid    = 0;
9cd8e5
	session.syspid = params.pbi.unique_process_id;
9cd8e5
9cd8e5
	if ((status = ntapi->tty_client_session_set(0,&session)))
9cd8e5
		ntapi->zw_terminate_process(
9cd8e5
			params.hprocess,
9cd8e5
			status);
9cd8e5
9cd8e5
	if ((status = ntapi->zw_resume_thread(params.hthread,0)))
9cd8e5
		ntapi->zw_terminate_process(
9cd8e5
			params.hprocess,
9cd8e5
			status);
9cd8e5
9cd8e5
	hchild[1] = params.hprocess;
9cd8e5
	hchild[0] = rdata->hready;
9cd8e5
9cd8e5
	ntapi->zw_wait_for_multiple_objects(
9cd8e5
		2,hchild,
9cd8e5
		NT_WAIT_ANY,
9cd8e5
		NT_SYNC_NON_ALERTABLE,
9cd8e5
		0);
9cd8e5
9cd8e5
	return ptyc_spawn_return(
9cd8e5
		&rtblock,status);
9cd8e5
}