|
|
a823bc |
|
|
|
268ef4 |
/********************************************************/
|
|
|
268ef4 |
/* ntapi: Native API core library */
|
|
|
64e606 |
/* Copyright (C) 2013--2021 SysDeer Technologies, LLC */
|
|
|
268ef4 |
/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
|
|
|
268ef4 |
/********************************************************/
|
|
|
268ef4 |
|
|
|
268ef4 |
#include <psxtypes/psxtypes.h>
|
|
|
268ef4 |
#include <ntapi/nt_atomic.h>
|
|
|
268ef4 |
#include <ntapi/nt_status.h>
|
|
|
268ef4 |
#include <ntapi/nt_object.h>
|
|
|
268ef4 |
#include <ntapi/nt_memory.h>
|
|
|
268ef4 |
#include <ntapi/nt_thread.h>
|
|
|
268ef4 |
#include <ntapi/nt_process.h>
|
|
|
268ef4 |
#include <ntapi/ntapi.h>
|
|
|
268ef4 |
#include "ntapi_impl.h"
|
|
|
268ef4 |
|
|
|
0a9ee4 |
#define __FORK_THREAD_STACK_COMMIT (0x10000)
|
|
|
0a9ee4 |
#define __FORK_THREAD_STACK_RESERVE (0x20000)
|
|
|
0a9ee4 |
|
|
|
268ef4 |
static intptr_t __fork_retry_stats = 0;
|
|
|
268ef4 |
static intptr_t __fork_resume_stats = 0;
|
|
|
268ef4 |
|
|
|
3841d3 |
static int __ipc_memfn(
|
|
|
3841d3 |
struct dalist_ex * dlist,
|
|
|
3841d3 |
void ** addr,
|
|
|
3841d3 |
size_t * alloc_size)
|
|
|
3841d3 |
{
|
|
|
3841d3 |
(void)dlist;
|
|
|
3841d3 |
(void)addr;
|
|
|
3841d3 |
(void)alloc_size;
|
|
|
3841d3 |
|
|
|
3841d3 |
return DALIST_EMEMFN;
|
|
|
3841d3 |
}
|
|
|
3841d3 |
|
|
|
a823bc |
static int32_t __fastcall __ntapi_tt_fork_finalize(void ** hprocess)
|
|
|
72fe5e |
{
|
|
|
72fe5e |
int32_t status;
|
|
|
30d28d |
int page;
|
|
|
edb085 |
nt_rtdata * rtdata;
|
|
|
72fe5e |
ntapi_internals * __internals;
|
|
|
72fe5e |
|
|
|
72fe5e |
__internals = __ntapi_internals();
|
|
|
edb085 |
rtdata = __internals->rtdata;
|
|
|
72fe5e |
|
|
|
abd389 |
rtdata->cid_parent.process_id = rtdata->cid_self.process_id;
|
|
|
abd389 |
rtdata->cid_parent.thread_id = rtdata->cid_self.thread_id;
|
|
|
abd389 |
|
|
|
abd389 |
rtdata->cid_self.process_id = pe_get_current_process_id();
|
|
|
abd389 |
rtdata->cid_self.thread_id = pe_get_current_thread_id();
|
|
|
abd389 |
|
|
|
80b89c |
if ((status = __ntapi->zw_duplicate_object(
|
|
|
80b89c |
__internals->hprocess,
|
|
|
80b89c |
__internals->hprocess,
|
|
|
80b89c |
__internals->hprocess,
|
|
|
80b89c |
hprocess,0,0,
|
|
|
80b89c |
NT_DUPLICATE_SAME_ATTRIBUTES
|
|
|
80b89c |
|NT_DUPLICATE_SAME_ACCESS)))
|
|
|
72fe5e |
return status;
|
|
|
72fe5e |
|
|
|
30d28d |
if ((status = dalist_init_ex(
|
|
|
30d28d |
&__internals->ipc_conns,
|
|
|
30d28d |
sizeof(nt_ipc_conn),
|
|
|
30d28d |
NT_ALLOCATION_GRANULARITY,
|
|
|
3841d3 |
__ipc_memfn,
|
|
|
30d28d |
DALIST_MEMFN_CUSTOM)))
|
|
|
30d28d |
return status;
|
|
|
30d28d |
|
|
|
30d28d |
dalist_deposit_memory_block(
|
|
|
30d28d |
&__internals->ipc_conns,
|
|
|
30d28d |
__internals->ntapi_img_sec_bss->ipc_buffer,
|
|
|
30d28d |
__NT_BSS_IPC_BUFFER_SIZE);
|
|
|
30d28d |
|
|
|
846d29 |
for (page=0; page<__internals->ipc_page; page++)
|
|
|
30d28d |
dalist_deposit_memory_block(
|
|
|
30d28d |
&__internals->ipc_conns,
|
|
|
30d28d |
__internals->ipc_pages[page],
|
|
|
30d28d |
NT_ALLOCATION_GRANULARITY);
|
|
|
30d28d |
|
|
|
edb085 |
rtdata->hsemctl = 0;
|
|
|
edb085 |
rtdata->hsempid = 0;
|
|
|
edb085 |
|
|
|
47f21a |
rtdata->hmsqctl = 0;
|
|
|
47f21a |
rtdata->hmsqpid = 0;
|
|
|
47f21a |
|
|
|
dbeebd |
rtdata->haflctl = 0;
|
|
|
dbeebd |
rtdata->haflpid = 0;
|
|
|
dbeebd |
|
|
|
edb085 |
rtdata->ipc_keys[0] = 0;
|
|
|
edb085 |
rtdata->ipc_keys[1] = 0;
|
|
|
edb085 |
rtdata->ipc_keys[2] = 0;
|
|
|
edb085 |
rtdata->ipc_keys[3] = 0;
|
|
|
edb085 |
rtdata->ipc_keys[4] = 0;
|
|
|
edb085 |
rtdata->ipc_keys[5] = 0;
|
|
|
edb085 |
|
|
|
a823bc |
return NT_STATUS_SUCCESS;
|
|
|
72fe5e |
}
|
|
|
72fe5e |
|
|
|
268ef4 |
static int32_t __stdcall __fork_thread(void * ctx)
|
|
|
268ef4 |
{
|
|
|
268ef4 |
intptr_t * pstate;
|
|
|
268ef4 |
intptr_t state;
|
|
|
268ef4 |
void * hready;
|
|
|
268ef4 |
|
|
|
268ef4 |
pstate = (intptr_t *)ctx;
|
|
|
268ef4 |
state = *pstate;
|
|
|
268ef4 |
hready = (void *)state;
|
|
|
268ef4 |
|
|
|
268ef4 |
at_store(
|
|
|
268ef4 |
pstate,
|
|
|
268ef4 |
0);
|
|
|
268ef4 |
|
|
|
268ef4 |
return __ntapi->zw_terminate_thread(
|
|
|
268ef4 |
NT_CURRENT_THREAD_HANDLE,
|
|
|
268ef4 |
__ntapi->zw_set_event(
|
|
|
268ef4 |
hready,0));
|
|
|
268ef4 |
}
|
|
|
268ef4 |
|
|
|
a823bc |
static int32_t __fastcall __ntapi_tt_fork_child(
|
|
|
268ef4 |
void * hresumed,
|
|
|
80b89c |
void * hready,
|
|
|
80b89c |
void ** hthread)
|
|
|
268ef4 |
{
|
|
|
268ef4 |
int32_t status;
|
|
|
268ef4 |
nt_thread_params tparams;
|
|
|
268ef4 |
nt_timeout timeout;
|
|
|
268ef4 |
nt_timeout zerowait;
|
|
|
268ef4 |
intptr_t state;
|
|
|
80b89c |
nt_oa oa;
|
|
|
80b89c |
nt_cid cid;
|
|
|
80b89c |
ntapi_internals * __internals;
|
|
|
80b89c |
|
|
|
80b89c |
oa.len = sizeof(oa);
|
|
|
80b89c |
oa.root_dir = 0;
|
|
|
80b89c |
oa.obj_name = 0;
|
|
|
80b89c |
oa.obj_attr = 0;
|
|
|
80b89c |
oa.sec_desc = &__internals->seq_desc;
|
|
|
80b89c |
oa.sec_qos = &__internals->seq_qos;
|
|
|
80b89c |
|
|
|
80b89c |
cid.process_id = pe_get_current_process_id();
|
|
|
80b89c |
cid.thread_id = pe_get_current_thread_id();
|
|
|
80b89c |
|
|
|
80b89c |
__internals = __ntapi_internals();
|
|
|
80b89c |
|
|
|
80b89c |
status = __ntapi->zw_open_process(
|
|
|
80b89c |
&__internals->hprocess,
|
|
|
80b89c |
NT_PROCESS_ALL_ACCESS,
|
|
|
80b89c |
&oa,&cid;;
|
|
|
80b89c |
|
|
|
80b89c |
if (status == NT_STATUS_SUCCESS)
|
|
|
80b89c |
status = __ntapi->zw_open_thread(
|
|
|
80b89c |
hthread,
|
|
|
80b89c |
NT_THREAD_ALL_ACCESS,
|
|
|
80b89c |
&oa,&cid;;
|
|
|
80b89c |
|
|
|
80b89c |
if (status) {
|
|
|
80b89c |
__ntapi->zw_set_event(
|
|
|
80b89c |
hresumed,0);
|
|
|
80b89c |
|
|
|
80b89c |
__ntapi->zw_terminate_process(
|
|
|
80b89c |
NT_CURRENT_PROCESS_HANDLE,
|
|
|
80b89c |
status);
|
|
|
80b89c |
}
|
|
|
268ef4 |
|
|
|
268ef4 |
at_store(
|
|
|
268ef4 |
&state,
|
|
|
268ef4 |
(intptr_t)hready);
|
|
|
268ef4 |
|
|
|
268ef4 |
__ntapi->tt_aligned_block_memset(
|
|
|
268ef4 |
&tparams,0,sizeof(tparams));
|
|
|
268ef4 |
|
|
|
268ef4 |
tparams.start = __fork_thread;
|
|
|
268ef4 |
tparams.arg = &stat;;
|
|
|
0a9ee4 |
tparams.stack_size_commit = __FORK_THREAD_STACK_COMMIT;
|
|
|
0a9ee4 |
tparams.stack_size_reserve = __FORK_THREAD_STACK_RESERVE;
|
|
|
268ef4 |
|
|
|
268ef4 |
status = __ntapi->tt_create_local_thread(
|
|
|
268ef4 |
&tparams);
|
|
|
268ef4 |
|
|
|
268ef4 |
__ntapi->zw_set_event(
|
|
|
268ef4 |
hresumed,0);
|
|
|
268ef4 |
|
|
|
268ef4 |
if (status)
|
|
|
268ef4 |
__ntapi->zw_terminate_process(
|
|
|
268ef4 |
NT_CURRENT_PROCESS_HANDLE,
|
|
|
268ef4 |
status);
|
|
|
268ef4 |
|
|
|
268ef4 |
if (!state) {
|
|
|
268ef4 |
__ntapi->zw_close(hresumed);
|
|
|
268ef4 |
__ntapi->zw_close(hready);
|
|
|
268ef4 |
__ntapi->zw_close(tparams.hthread);
|
|
|
a823bc |
return NT_STATUS_SUCCESS;
|
|
|
268ef4 |
}
|
|
|
268ef4 |
|
|
|
268ef4 |
timeout.quad = (-1) * 10 * 1000 * 250;
|
|
|
268ef4 |
|
|
|
268ef4 |
status = __ntapi->zw_wait_for_single_object(
|
|
|
268ef4 |
hready,
|
|
|
268ef4 |
NT_SYNC_NON_ALERTABLE,
|
|
|
268ef4 |
&timeout);
|
|
|
268ef4 |
|
|
|
268ef4 |
if (status == NT_STATUS_SUCCESS) {
|
|
|
268ef4 |
__ntapi->zw_close(hresumed);
|
|
|
268ef4 |
__ntapi->zw_close(hready);
|
|
|
268ef4 |
__ntapi->zw_close(tparams.hthread);
|
|
|
a823bc |
return NT_STATUS_SUCCESS;
|
|
|
268ef4 |
}
|
|
|
268ef4 |
|
|
|
268ef4 |
__ntapi->zw_terminate_thread(
|
|
|
268ef4 |
tparams.hthread,
|
|
|
268ef4 |
NT_STATUS_MORE_PROCESSING_REQUIRED);
|
|
|
268ef4 |
|
|
|
268ef4 |
zerowait.quad = 0;
|
|
|
268ef4 |
|
|
|
268ef4 |
status = __ntapi->zw_wait_for_single_object(
|
|
|
268ef4 |
hready,
|
|
|
268ef4 |
NT_SYNC_NON_ALERTABLE,
|
|
|
268ef4 |
&zerowait);
|
|
|
268ef4 |
|
|
|
268ef4 |
if (status == NT_STATUS_SUCCESS) {
|
|
|
268ef4 |
__ntapi->zw_close(hresumed);
|
|
|
268ef4 |
__ntapi->zw_close(hready);
|
|
|
268ef4 |
__ntapi->zw_close(tparams.hthread);
|
|
|
a823bc |
return NT_STATUS_SUCCESS;
|
|
|
268ef4 |
}
|
|
|
268ef4 |
|
|
|
268ef4 |
return __ntapi->zw_terminate_process(
|
|
|
268ef4 |
NT_CURRENT_PROCESS_HANDLE,
|
|
|
268ef4 |
status);
|
|
|
268ef4 |
}
|
|
|
268ef4 |
|
|
|
268ef4 |
static intptr_t __fastcall __ntapi_tt_fork_parent(
|
|
|
268ef4 |
void ** hprocess,
|
|
|
268ef4 |
void ** hthread,
|
|
|
268ef4 |
void * hresumed,
|
|
|
268ef4 |
void * hready)
|
|
|
268ef4 |
{
|
|
|
268ef4 |
int32_t status;
|
|
|
268ef4 |
nt_timeout timeout;
|
|
|
268ef4 |
nt_timeout zerowait;
|
|
|
268ef4 |
uint32_t prev;
|
|
|
268ef4 |
|
|
|
268ef4 |
__ntapi->zw_wait_for_single_object(
|
|
|
268ef4 |
hresumed,
|
|
|
268ef4 |
NT_SYNC_NON_ALERTABLE,
|
|
|
268ef4 |
0);
|
|
|
268ef4 |
|
|
|
268ef4 |
timeout.quad = (-1) * 10 * 1000 * 500;
|
|
|
268ef4 |
|
|
|
268ef4 |
status = __ntapi->zw_wait_for_single_object(
|
|
|
268ef4 |
hready,
|
|
|
268ef4 |
NT_SYNC_NON_ALERTABLE,
|
|
|
268ef4 |
&timeout);
|
|
|
268ef4 |
|
|
|
a823bc |
if (status == NT_STATUS_SUCCESS)
|
|
|
268ef4 |
return NT_STATUS_SUCCESS;
|
|
|
268ef4 |
|
|
|
268ef4 |
__ntapi->zw_suspend_thread(
|
|
|
268ef4 |
*hthread,&prev;;
|
|
|
268ef4 |
|
|
|
268ef4 |
zerowait.quad = 0;
|
|
|
268ef4 |
|
|
|
268ef4 |
status = __ntapi->zw_wait_for_single_object(
|
|
|
268ef4 |
hready,
|
|
|
268ef4 |
NT_SYNC_NON_ALERTABLE,
|
|
|
268ef4 |
&zerowait);
|
|
|
268ef4 |
|
|
|
268ef4 |
if (status == NT_STATUS_SUCCESS) {
|
|
|
268ef4 |
at_locked_inc(
|
|
|
268ef4 |
&__fork_resume_stats);
|
|
|
268ef4 |
|
|
|
268ef4 |
__ntapi->zw_resume_thread(
|
|
|
268ef4 |
*hthread,0);
|
|
|
268ef4 |
|
|
|
268ef4 |
return NT_STATUS_SUCCESS;
|
|
|
268ef4 |
}
|
|
|
268ef4 |
|
|
|
268ef4 |
at_locked_inc(
|
|
|
268ef4 |
&__fork_retry_stats);
|
|
|
268ef4 |
|
|
|
268ef4 |
__ntapi->zw_terminate_process(
|
|
|
268ef4 |
*hprocess,
|
|
|
268ef4 |
status);
|
|
|
268ef4 |
|
|
|
268ef4 |
__ntapi->zw_close(*hprocess);
|
|
|
268ef4 |
__ntapi->zw_close(*hthread);
|
|
|
268ef4 |
|
|
|
268ef4 |
return status;
|
|
|
268ef4 |
}
|
|
|
268ef4 |
|
|
|
a823bc |
int32_t __fastcall __ntapi_tt_fork(
|
|
|
268ef4 |
__out void ** hprocess,
|
|
|
a823bc |
__out void ** hthread,
|
|
|
a823bc |
__out nt_cid * cid)
|
|
|
268ef4 |
{
|
|
|
268ef4 |
int32_t status;
|
|
|
268ef4 |
void * hresumed;
|
|
|
268ef4 |
void * hready;
|
|
|
268ef4 |
int i;
|
|
|
268ef4 |
|
|
|
268ef4 |
if ((status = __ntapi->tt_create_inheritable_event(
|
|
|
268ef4 |
&hresumed,
|
|
|
268ef4 |
NT_NOTIFICATION_EVENT,
|
|
|
268ef4 |
NT_EVENT_NOT_SIGNALED)))
|
|
|
a823bc |
return status;
|
|
|
268ef4 |
|
|
|
25d708 |
status = __ntapi->tt_create_inheritable_event(
|
|
|
25d708 |
&hready,
|
|
|
25d708 |
NT_NOTIFICATION_EVENT,
|
|
|
25d708 |
NT_EVENT_NOT_SIGNALED);
|
|
|
25d708 |
|
|
|
25d708 |
if (status) {
|
|
|
25d708 |
__ntapi->zw_close(hresumed);
|
|
|
a823bc |
return status;
|
|
|
25d708 |
}
|
|
|
268ef4 |
|
|
|
268ef4 |
for (i=0; i<32; i++) {
|
|
|
268ef4 |
if (__ntapi->zw_create_user_process)
|
|
|
a823bc |
status = __ntapi_tt_fork_v2(hprocess,hthread,cid);
|
|
|
268ef4 |
else
|
|
|
a823bc |
status = __ntapi_tt_fork_v1(hprocess,hthread,cid);
|
|
|
268ef4 |
|
|
|
a823bc |
if (status) {
|
|
|
a823bc |
__ntapi->zw_close(hresumed);
|
|
|
a823bc |
__ntapi->zw_close(hready);
|
|
|
a823bc |
return status;
|
|
|
a823bc |
}
|
|
|
a823bc |
|
|
|
a823bc |
if (cid->process_id == 0) {
|
|
|
72fe5e |
__ntapi_tt_fork_child(
|
|
|
80b89c |
hresumed,hready,hthread);
|
|
|
268ef4 |
|
|
|
72fe5e |
return __ntapi_tt_fork_finalize(
|
|
|
80b89c |
hprocess);
|
|
|
a823bc |
}
|
|
|
72fe5e |
|
|
|
a823bc |
status = __ntapi_tt_fork_parent(
|
|
|
a823bc |
hprocess,hthread,
|
|
|
a823bc |
hresumed,hready);
|
|
|
268ef4 |
|
|
|
a823bc |
if (status == NT_STATUS_SUCCESS) {
|
|
|
268ef4 |
__ntapi->zw_close(hresumed);
|
|
|
268ef4 |
__ntapi->zw_close(hready);
|
|
|
a823bc |
return NT_STATUS_SUCCESS;
|
|
|
268ef4 |
}
|
|
|
268ef4 |
}
|
|
|
268ef4 |
|
|
|
268ef4 |
__ntapi->zw_close(hresumed);
|
|
|
268ef4 |
__ntapi->zw_close(hready);
|
|
|
268ef4 |
|
|
|
a823bc |
return NT_STATUS_UNSUCCESSFUL;
|
|
|
268ef4 |
}
|