|
|
268ef4 |
/********************************************************/
|
|
|
268ef4 |
/* ntapi: Native API core library */
|
|
|
dde53a |
/* Copyright (C) 2013--2017 Z. Gilboa */
|
|
|
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 |
|
|
|
268ef4 |
static intptr_t __fork_retry_stats = 0;
|
|
|
268ef4 |
static intptr_t __fork_resume_stats = 0;
|
|
|
268ef4 |
|
|
|
72fe5e |
static intptr_t __fastcall __ntapi_tt_fork_finalize(
|
|
|
72fe5e |
void ** hprocess,
|
|
|
72fe5e |
void ** hthread)
|
|
|
72fe5e |
{
|
|
|
72fe5e |
int32_t status;
|
|
|
72fe5e |
nt_oa oa;
|
|
|
72fe5e |
nt_cid cid;
|
|
|
30d28d |
int page;
|
|
|
72fe5e |
ntapi_internals * __internals;
|
|
|
72fe5e |
|
|
|
72fe5e |
__internals = __ntapi_internals();
|
|
|
72fe5e |
|
|
|
72fe5e |
*hprocess = 0;
|
|
|
72fe5e |
*hthread = 0;
|
|
|
72fe5e |
|
|
|
72fe5e |
oa.len = sizeof(oa);
|
|
|
72fe5e |
oa.root_dir = 0;
|
|
|
72fe5e |
oa.obj_name = 0;
|
|
|
72fe5e |
oa.obj_attr = 0;
|
|
|
72fe5e |
oa.sec_desc = &__internals->seq_desc;
|
|
|
72fe5e |
oa.sec_qos = &__internals->seq_qos;
|
|
|
72fe5e |
|
|
|
72fe5e |
cid.process_id = pe_get_current_process_id();
|
|
|
72fe5e |
cid.thread_id = pe_get_current_thread_id();
|
|
|
72fe5e |
|
|
|
72fe5e |
if ((status = __ntapi->zw_open_process(
|
|
|
72fe5e |
hprocess,
|
|
|
72fe5e |
NT_PROCESS_ALL_ACCESS,
|
|
|
72fe5e |
&oa,&cid)))
|
|
|
72fe5e |
return status;
|
|
|
72fe5e |
|
|
|
72fe5e |
if ((status = __ntapi->zw_open_thread(
|
|
|
72fe5e |
hthread,
|
|
|
72fe5e |
NT_THREAD_ALL_ACCESS,
|
|
|
72fe5e |
&oa,&cid)))
|
|
|
72fe5e |
return status;
|
|
|
72fe5e |
|
|
|
30d28d |
if ((status = dalist_init_ex(
|
|
|
30d28d |
&__internals->ipc_conns,
|
|
|
30d28d |
sizeof(nt_ipc_conn),
|
|
|
30d28d |
NT_ALLOCATION_GRANULARITY,
|
|
|
30d28d |
__ntapi_ipc_page_alloc,
|
|
|
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 |
|
|
|
30d28d |
for (page=0; __internals->ipc_page; page++)
|
|
|
30d28d |
dalist_deposit_memory_block(
|
|
|
30d28d |
&__internals->ipc_conns,
|
|
|
30d28d |
__internals->ipc_pages[page],
|
|
|
30d28d |
NT_ALLOCATION_GRANULARITY);
|
|
|
30d28d |
|
|
|
72fe5e |
return 0;
|
|
|
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 |
|
|
|
268ef4 |
static intptr_t __fastcall __ntapi_tt_fork_child(
|
|
|
268ef4 |
void * hresumed,
|
|
|
268ef4 |
void * hready)
|
|
|
268ef4 |
{
|
|
|
268ef4 |
int32_t status;
|
|
|
268ef4 |
nt_thread_params tparams;
|
|
|
268ef4 |
nt_timeout timeout;
|
|
|
268ef4 |
nt_timeout zerowait;
|
|
|
268ef4 |
intptr_t state;
|
|
|
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;;
|
|
|
268ef4 |
tparams.stack_size_commit = 0x10000;
|
|
|
268ef4 |
tparams.stack_size_reserve = 0x20000;
|
|
|
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);
|
|
|
268ef4 |
return 0;
|
|
|
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);
|
|
|
268ef4 |
return 0;
|
|
|
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);
|
|
|
268ef4 |
return 0;
|
|
|
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 |
|
|
|
268ef4 |
if (status == NT_STATUS_SUCCESS) {
|
|
|
268ef4 |
__ntapi->zw_close(hresumed);
|
|
|
268ef4 |
__ntapi->zw_close(hready);
|
|
|
268ef4 |
return NT_STATUS_SUCCESS;
|
|
|
268ef4 |
}
|
|
|
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 |
__ntapi->zw_close(hresumed);
|
|
|
268ef4 |
__ntapi->zw_close(hready);
|
|
|
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 |
|
|
|
268ef4 |
intptr_t __fastcall __ntapi_tt_fork(
|
|
|
268ef4 |
__out void ** hprocess,
|
|
|
268ef4 |
__out void ** hthread)
|
|
|
268ef4 |
{
|
|
|
268ef4 |
int32_t status;
|
|
|
268ef4 |
intptr_t pid;
|
|
|
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)))
|
|
|
268ef4 |
return -1;
|
|
|
268ef4 |
|
|
|
268ef4 |
if ((status = __ntapi->tt_create_inheritable_event(
|
|
|
268ef4 |
&hready,
|
|
|
268ef4 |
NT_NOTIFICATION_EVENT,
|
|
|
268ef4 |
NT_EVENT_NOT_SIGNALED)))
|
|
|
268ef4 |
return -1;
|
|
|
268ef4 |
|
|
|
268ef4 |
for (i=0; i<32; i++) {
|
|
|
268ef4 |
if (__ntapi->zw_create_user_process)
|
|
|
268ef4 |
pid = __ntapi_tt_fork_v2(hprocess,hthread);
|
|
|
268ef4 |
else
|
|
|
268ef4 |
pid = __ntapi_tt_fork_v2(hprocess,hthread);
|
|
|
268ef4 |
|
|
|
268ef4 |
if (pid == 0) {
|
|
|
72fe5e |
__ntapi_tt_fork_child(
|
|
|
268ef4 |
hresumed,hready);
|
|
|
268ef4 |
|
|
|
72fe5e |
return __ntapi_tt_fork_finalize(
|
|
|
72fe5e |
hprocess,hthread);
|
|
|
72fe5e |
|
|
|
268ef4 |
} else if (pid > 0) {
|
|
|
268ef4 |
if (!(__ntapi_tt_fork_parent(
|
|
|
268ef4 |
hprocess,hthread,
|
|
|
268ef4 |
hresumed,hready)))
|
|
|
268ef4 |
return pid;
|
|
|
268ef4 |
|
|
|
268ef4 |
} else {
|
|
|
268ef4 |
__ntapi->zw_close(hresumed);
|
|
|
268ef4 |
__ntapi->zw_close(hready);
|
|
|
268ef4 |
return -1;
|
|
|
268ef4 |
}
|
|
|
268ef4 |
}
|
|
|
268ef4 |
|
|
|
268ef4 |
__ntapi->zw_close(hresumed);
|
|
|
268ef4 |
__ntapi->zw_close(hready);
|
|
|
268ef4 |
|
|
|
268ef4 |
return -1;
|
|
|
268ef4 |
}
|