|
|
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/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_string.h>
|
|
|
dd89bb |
#include <ntapi/ntapi.h>
|
|
|
dd89bb |
#include "ntapi_impl.h"
|
|
|
dd89bb |
|
|
|
dd89bb |
intptr_t __cdecl __attr_hidden__ __tt_fork_v1(void);
|
|
|
dd89bb |
uint32_t __fastcall __attr_hidden__ __tt_fork_child_entry_point(uintptr_t saved_regs_stack_pointer);
|
|
|
dd89bb |
uint32_t __fastcall __attr_hidden__ __tt_fork_child_entry_point_adj(uintptr_t saved_regs_stack_pointer);
|
|
|
dd89bb |
|
|
|
dd89bb |
/** legacy fork chronology:
|
|
|
dd89bb |
*
|
|
|
dd89bb |
* parent:
|
|
|
dd89bb |
* __ntapi_tt_fork ->
|
|
|
dd89bb |
* __tt_fork ->
|
|
|
dd89bb |
* __tt_fork_impl ->
|
|
|
dd89bb |
* return to __tt_fork -->
|
|
|
dd89bb |
* __ntapi_tt_fork
|
|
|
dd89bb |
* -> return to caller
|
|
|
dd89bb |
*
|
|
|
dd89bb |
* child:
|
|
|
dd89bb |
* __tt_fork_child_entry_point[_adj] ->
|
|
|
dd89bb |
* __ntapi_tt_fork (internal return) ->
|
|
|
dd89bb |
* -> return to caller
|
|
|
dd89bb |
**/
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
static intptr_t __tt_fork_cancel(void * hprocess,int32_t status)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
__ntapi->zw_terminate_process(hprocess, status);
|
|
|
dd89bb |
__ntapi->zw_close(hprocess);
|
|
|
dd89bb |
return (intptr_t)(-1);
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
766a63 |
__attr_protected__
|
|
|
dd89bb |
intptr_t __fastcall __tt_fork_impl_v1(
|
|
|
dd89bb |
uintptr_t saved_regs_stack_pointer,
|
|
|
dd89bb |
uintptr_t stack_adjustment)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
int32_t status;
|
|
|
dd89bb |
void * hprocess;
|
|
|
dd89bb |
void * hthread;
|
|
|
dd89bb |
void ** hport_session;
|
|
|
dd89bb |
ntapi_internals * __internals;
|
|
|
dd89bb |
|
|
|
dd89bb |
nt_object_attributes oa;
|
|
|
dd89bb |
nt_process_basic_information pbi;
|
|
|
dd89bb |
nt_thread_context context;
|
|
|
dd89bb |
nt_user_stack stack;
|
|
|
dd89bb |
nt_memory_basic_information mbi;
|
|
|
dd89bb |
nt_client_id cid;
|
|
|
dd89bb |
nt_large_integer timeout;
|
|
|
dd89bb |
|
|
|
5489c6 |
hprocess = 0;
|
|
|
5489c6 |
hthread = 0;
|
|
|
dd89bb |
|
|
|
dd89bb |
oa.len = sizeof(nt_object_attributes);
|
|
|
dd89bb |
oa.root_dir = 0;
|
|
|
dd89bb |
oa.obj_name = 0;
|
|
|
dd89bb |
oa.obj_attr = 0;
|
|
|
dd89bb |
oa.sec_desc = 0;
|
|
|
dd89bb |
oa.sec_qos = 0;
|
|
|
dd89bb |
|
|
|
dd89bb |
if ((status = __ntapi->zw_create_process(
|
|
|
dd89bb |
&hprocess,
|
|
|
dd89bb |
NT_PROCESS_ALL_ACCESS,
|
|
|
dd89bb |
&oa,
|
|
|
dd89bb |
NT_CURRENT_PROCESS_HANDLE,
|
|
|
dd89bb |
1,0,0,0)))
|
|
|
dd89bb |
return (intptr_t)(-1);
|
|
|
dd89bb |
|
|
|
dd89bb |
if ((status = __ntapi->zw_query_information_process(
|
|
|
dd89bb |
hprocess,
|
|
|
dd89bb |
NT_PROCESS_BASIC_INFORMATION,
|
|
|
dd89bb |
(void *)&pbi,
|
|
|
dd89bb |
sizeof(nt_process_basic_information),
|
|
|
dd89bb |
0)))
|
|
|
dd89bb |
return __tt_fork_cancel(hprocess,status);
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
__ntapi->tt_aligned_block_memset(
|
|
|
dd89bb |
&context,0,sizeof(nt_thread_context));
|
|
|
dd89bb |
|
|
|
dd89bb |
__INIT_CONTEXT(context);
|
|
|
dd89bb |
context.STACK_POINTER_REGISTER = saved_regs_stack_pointer;
|
|
|
dd89bb |
context.FAST_CALL_ARG0 = saved_regs_stack_pointer;
|
|
|
dd89bb |
|
|
|
dd89bb |
context.INSTRUCTION_POINTER_REGISTER = stack_adjustment
|
|
|
dd89bb |
? (uintptr_t)__tt_fork_child_entry_point_adj
|
|
|
dd89bb |
: (uintptr_t)__tt_fork_child_entry_point;
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
if ((status = __ntapi->zw_query_virtual_memory(
|
|
|
dd89bb |
NT_CURRENT_PROCESS_HANDLE,
|
|
|
dd89bb |
(void *)context.STACK_POINTER_REGISTER,
|
|
|
dd89bb |
NT_MEMORY_BASIC_INFORMATION,
|
|
|
dd89bb |
&mbi,sizeof(nt_memory_basic_information),0)))
|
|
|
dd89bb |
return __tt_fork_cancel(hprocess,status);
|
|
|
dd89bb |
|
|
|
dd89bb |
stack.fixed_stack_base = (void *)0;
|
|
|
dd89bb |
stack.fixed_stack_limit = (void *)0;
|
|
|
dd89bb |
stack.expandable_stack_base = (void *)((uintptr_t)mbi.base_address + mbi.region_size);
|
|
|
dd89bb |
stack.expandable_stack_limit = (void *)mbi.base_address;
|
|
|
dd89bb |
stack.expandable_stack_bottom = (void *)mbi.allocation_base;
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
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,
|
|
|
dd89bb |
pbi.unique_process_id,
|
|
|
dd89bb |
0, 0, &timeout)))
|
|
|
dd89bb |
return __tt_fork_cancel(hprocess,status);
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
if ((status = __ntapi->zw_create_thread(
|
|
|
dd89bb |
&hthread,
|
|
|
dd89bb |
NT_THREAD_ALL_ACCESS,
|
|
|
dd89bb |
&oa,hprocess,&cid,
|
|
|
dd89bb |
&context,&stack,0)))
|
|
|
dd89bb |
return __tt_fork_cancel(hprocess,status);
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
if (cid.process_id > 0) {
|
|
|
dd89bb |
__internals->hany[0] = hprocess;
|
|
|
dd89bb |
__internals->hany[1] = hthread;
|
|
|
dd89bb |
} else {
|
|
|
dd89bb |
__internals->hany[0] = 0;
|
|
|
dd89bb |
__internals->hany[1] = 0;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
/* hoppla */
|
|
|
dd89bb |
return (int32_t)cid.process_id;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
intptr_t __fastcall __ntapi_tt_fork_v1(
|
|
|
dd89bb |
__out void ** hprocess,
|
|
|
dd89bb |
__out void ** hthread)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
int32_t status;
|
|
|
dd89bb |
intptr_t pid;
|
|
|
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 |
|
|
|
4a5679 |
while (at_locked_cas(&__internals->hlock,0,1))
|
|
|
4a5679 |
__ntapi->zw_delay_execution(
|
|
|
4a5679 |
NT_SYNC_NON_ALERTABLE,
|
|
|
4a5679 |
&(nt_timeout){{0,0}});
|
|
|
dd89bb |
|
|
|
4a5679 |
if (hport_session && *hport_session) {
|
|
|
dd89bb |
if (__ntapi_tt_create_inheritable_event(
|
|
|
5489c6 |
&htty_connected,
|
|
|
dd89bb |
NT_NOTIFICATION_EVENT,
|
|
|
4a5679 |
NT_EVENT_NOT_SIGNALED)) {
|
|
|
4a5679 |
at_store(&__internals->hlock,0);
|
|
|
dd89bb |
return (intptr_t)(-1);
|
|
|
4a5679 |
}
|
|
|
4a5679 |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
pid = __tt_fork_v1();
|
|
|
dd89bb |
|
|
|
dd89bb |
*hprocess = __internals->hany[0];
|
|
|
dd89bb |
*hthread = __internals->hany[1];
|
|
|
dd89bb |
|
|
|
dd89bb |
at_store(&__internals->hlock,0);
|
|
|
dd89bb |
|
|
|
dd89bb |
if (hport_session && *hport_session) {
|
|
|
dd89bb |
if (pid == 0) {
|
|
|
dd89bb |
if ((status = __ntapi->tty_connect(
|
|
|
dd89bb |
hport_session,
|
|
|
dd89bb |
__internals->subsystem->base_named_objects,
|
|
|
dd89bb |
NT_SECURITY_IMPERSONATION)))
|
|
|
dd89bb |
return __tt_fork_cancel(NT_CURRENT_PROCESS_HANDLE,status);
|
|
|
dd89bb |
|
|
|
dd89bb |
__internals->hdev_mount_point_mgr = 0;
|
|
|
dd89bb |
|
|
|
dd89bb |
if (__internals->rtdata)
|
|
|
dd89bb |
__internals->rtdata->hsession = *hport_session;
|
|
|
dd89bb |
|
|
|
dd89bb |
__ntapi->zw_set_event(
|
|
|
5489c6 |
htty_connected,
|
|
|
dd89bb |
0);
|
|
|
dd89bb |
|
|
|
dd89bb |
} else if (pid > 0) {
|
|
|
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)))
|
|
|
dd89bb |
pid = __tt_fork_cancel(*hprocess,status);
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
5489c6 |
__ntapi->zw_close(htty_connected);
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
return pid;
|
|
|
dd89bb |
}
|