Blame src/process/ntapi_tt_fork_v2.c

dd89bb
/********************************************************/
dd89bb
/*  ntapi: Native API core library                      */
64e606
/*  Copyright (C) 2013--2021  SysDeer Technologies, LLC */
dd89bb
/*  Released under GPLv2 and GPLv3; see COPYING.NTAPI.  */
dd89bb
/********************************************************/
dd89bb
dd89bb
#include <psxtypes/psxtypes.h>
9a449a
#include <ntapi/nt_atomic.h>
dd89bb
#include <ntapi/nt_status.h>
dd89bb
#include <ntapi/nt_object.h>
dd89bb
#include <ntapi/nt_memory.h>
dd89bb
#include <ntapi/nt_thread.h>
dd89bb
#include <ntapi/nt_process.h>
dd89bb
#include <ntapi/nt_sync.h>
dd89bb
#include <ntapi/nt_string.h>
dd89bb
#include <ntapi/ntapi.h>
dd89bb
#include "ntapi_impl.h"
dd89bb
a9aec2
static intptr_t __tt_fork_cancel(void * hprocess,void * hthread,int32_t status)
dd89bb
{
345a52
	__ntapi->zw_terminate_process(hprocess,status);
dd89bb
	__ntapi->zw_close(hprocess);
a9aec2
	__ntapi->zw_close(hthread);
a823bc
	return status;
dd89bb
}
dd89bb
b677ca
static intptr_t __tt_fork_impl_v2(
a823bc
	__out	void **         hprocess,
a823bc
	__out	void **         hthread,
a823bc
	__out	nt_cid *        cid)
dd89bb
{
dd89bb
	int32_t			status;
dd89bb
	void **			hport_session;
dd89bb
	nt_object_attributes	oa_process;
dd89bb
	nt_object_attributes	oa_thread;
dd89bb
	nt_create_process_info	process_info;
dd89bb
	nt_sec_img_inf		sec_img_inf;
dd89bb
	nt_timeout		timeout;
dd89bb
	ntapi_internals *	__internals;
dd89bb
dd89bb
	struct {
dd89bb
		size_t				size_in_bytes;
dd89bb
		nt_create_process_ext_param	process_info;
dd89bb
		nt_create_process_ext_param	section_info;
dd89bb
	} ext_params;
dd89bb
dd89bb
dd89bb
	oa_process.len		= sizeof(nt_object_attributes);
dd89bb
	oa_process.root_dir	= 0;
dd89bb
	oa_process.obj_name	= 0;
dd89bb
	oa_process.obj_attr	= 0;
dd89bb
	oa_process.sec_desc	= 0;
dd89bb
	oa_process.sec_qos	= 0;
dd89bb
dd89bb
	oa_thread.len		= sizeof(nt_object_attributes);
dd89bb
	oa_thread.root_dir	= 0;
dd89bb
	oa_thread.obj_name	= 0;
dd89bb
	oa_thread.obj_attr	= 0;
dd89bb
	oa_thread.sec_desc	= 0;
dd89bb
	oa_thread.sec_qos	= 0;
dd89bb
a823bc
	cid->process_id = 0;
a823bc
	cid->thread_id  = 0;
dd89bb
dd89bb
	__ntapi->tt_aligned_block_memset(
dd89bb
		&process_info,0,sizeof(process_info));
dd89bb
dd89bb
	process_info.size			= sizeof(process_info);
dd89bb
	process_info.state			= NT_PROCESS_CREATE_INITIAL_STATE;
dd89bb
	process_info.init_state.init_flags	= NT_PROCESS_CREATE_FLAGS_NO_OBJECT_SYNC;
dd89bb
dd89bb
	__ntapi->tt_aligned_block_memset(&ext_params,0,sizeof(ext_params));
dd89bb
	__ntapi->tt_aligned_block_memset(&sec_img_inf,0,sizeof(sec_img_inf));
dd89bb
	ext_params.size_in_bytes = sizeof(ext_params);
dd89bb
dd89bb
	ext_params.process_info.ext_param_type	= NT_CREATE_PROCESS_EXT_PARAM_GET_CLIENT_ID;
a823bc
	ext_params.process_info.ext_param_size	= sizeof(*cid);
a823bc
	ext_params.process_info.ext_param_addr	= cid;
dd89bb
dd89bb
	ext_params.section_info.ext_param_type	= NT_CREATE_PROCESS_EXT_PARAM_GET_SECTION_IMAGE_INFO;
dd89bb
	ext_params.section_info.ext_param_size	= sizeof(sec_img_inf);
dd89bb
	ext_params.section_info.ext_param_addr	= &sec_img_inf;
dd89bb
dd89bb
dd89bb
	/* [thou shalt remember the single step paradox] */
dd89bb
	status = __ntapi->zw_create_user_process(
dd89bb
		hprocess,
dd89bb
		hthread,
dd89bb
		NT_PROCESS_ALL_ACCESS,
dd89bb
		NT_THREAD_ALL_ACCESS,
dd89bb
		&oa_process,
dd89bb
		&oa_thread,
dd89bb
		NT_PROCESS_CREATE_FLAGS_INHERIT_HANDLES,
dd89bb
		NT_PROCESS_CREATE_FLAGS_CREATE_THREAD_SUSPENDED,
dd89bb
		(nt_process_parameters *)0,
dd89bb
		&process_info,
dd89bb
		(nt_create_process_ext_params *)&ext_params);
dd89bb
a823bc
	switch (status) {
a823bc
		case NT_STATUS_PROCESS_CLONED:
a823bc
			return NT_STATUS_SUCCESS;
a823bc
a823bc
		case NT_STATUS_SUCCESS:
a823bc
			break;
a823bc
a823bc
		default:
a823bc
			return status;
a823bc
	}
dd89bb
dd89bb
	__internals	= __ntapi_internals();
dd89bb
	hport_session	= &__internals->hport_tty_session;
dd89bb
	timeout.quad	= (-1) * 10 * 1000 * __NT_FORK_CHILD_WAIT_MILLISEC;
dd89bb
dd89bb
	if (hport_session && *hport_session)
dd89bb
		if ((status = __ntapi->tty_client_process_register(
dd89bb
				*hport_session,
a823bc
				cid->process_id,
dd89bb
				0,0,&timeout)))
a9aec2
			return __tt_fork_cancel(*hprocess,*hthread,status);
dd89bb
dd89bb
	/* [thou shalt remember the single step paradox] */
dd89bb
	if ((status = __ntapi->zw_resume_thread(
dd89bb
			*hthread,0)))
a9aec2
		return __tt_fork_cancel(*hprocess,*hthread,status);
dd89bb
dd89bb
	/* hoppla */
a823bc
	return NT_STATUS_SUCCESS;
dd89bb
}
dd89bb
a823bc
int32_t __fastcall __ntapi_tt_fork_v2(
dd89bb
	__out	void **		hprocess,
a823bc
	__out	void **		hthread,
a823bc
	__out	nt_cid *	cid)
dd89bb
{
dd89bb
	int32_t			status;
dd89bb
	nt_large_integer	timeout;
dd89bb
	void **			hport_session;
5489c6
	void *			htty_connected;
dd89bb
	ntapi_internals *	__internals;
dd89bb
dd89bb
	__internals	= __ntapi_internals();
dd89bb
	hport_session	= &__internals->hport_tty_session;
dd89bb
	timeout.quad	= (-1) * 10 * 1000 * __NT_FORK_CHILD_WAIT_MILLISEC;
5489c6
	htty_connected  = 0;
dd89bb
dd89bb
	if (hport_session && *hport_session)
a823bc
		if ((status = __ntapi_tt_create_inheritable_event(
5489c6
				&htty_connected,
dd89bb
				NT_NOTIFICATION_EVENT,
a823bc
				NT_EVENT_NOT_SIGNALED)))
a823bc
			return status;
dd89bb
a823bc
	if ((status = __tt_fork_impl_v2(hprocess,hthread,cid)))
a823bc
		return status;
dd89bb
dd89bb
	if (!hport_session || !*hport_session)
a823bc
		return NT_STATUS_SUCCESS;
dd89bb
a823bc
	if (cid->process_id == 0) {
9a449a
		at_store(&__internals->hlock,0);
9a449a
a9aec2
		status = __ntapi->tty_connect(
a9aec2
			hport_session,
a9aec2
			__internals->subsystem->base_named_objects,
a9aec2
			NT_SECURITY_IMPERSONATION);
a9aec2
a9aec2
		if (status) {
a9aec2
			__ntapi->zw_terminate_process(
a9aec2
				NT_CURRENT_PROCESS_HANDLE,
a9aec2
				status);
a9aec2
a9aec2
			return NT_STATUS_INTERNAL_ERROR;
a9aec2
		}
dd89bb
4c5509
		__internals->hdev_mount_point_mgr = 0;
dd89bb
4c5509
		if (__internals->rtdata)
4c5509
			__internals->rtdata->hsession = *hport_session;
dd89bb
4c5509
		__ntapi->zw_set_event(
4c5509
			htty_connected,
4c5509
			0);
dd89bb
	} else {
dd89bb
		status = __ntapi->zw_wait_for_single_object(
5489c6
			htty_connected,
dd89bb
			NT_SYNC_NON_ALERTABLE,
dd89bb
			&timeout);
dd89bb
dd89bb
		if (status && __PSX_DEBUG)
dd89bb
			if ((status = __ntapi->zw_wait_for_single_object(
5489c6
					htty_connected,
dd89bb
					NT_SYNC_NON_ALERTABLE,
dd89bb
					0)))
a9aec2
				status = __tt_fork_cancel(*hprocess,*hthread,status);
dd89bb
	}
dd89bb
dd89bb
5489c6
	__ntapi->zw_close(htty_connected);
dd89bb
a823bc
	return status;
dd89bb
}