summaryrefslogtreecommitdiffhomepage
path: root/src/process/ntapi_tt_fork_v1.c
diff options
context:
space:
mode:
authormidipix <writeonce@midipix.org>2015-07-27 04:01:18 -0400
committermidipix <writeonce@midipix.org>2015-07-27 04:01:18 -0400
commitdd89bb8ad4fe184a34b5dbdda237e640fc82121b (patch)
tree5e80d2da35f5892f92be29f57982b2708e6bd99b /src/process/ntapi_tt_fork_v1.c
parentdcdadc2702712fa750ed255ed1dfa354522797a0 (diff)
downloadntapi-dd89bb8ad4fe184a34b5dbdda237e640fc82121b.tar.bz2
ntapi-dd89bb8ad4fe184a34b5dbdda237e640fc82121b.tar.xz
entered advanced internal development stage.
Diffstat (limited to 'src/process/ntapi_tt_fork_v1.c')
-rw-r--r--src/process/ntapi_tt_fork_v1.c218
1 files changed, 218 insertions, 0 deletions
diff --git a/src/process/ntapi_tt_fork_v1.c b/src/process/ntapi_tt_fork_v1.c
new file mode 100644
index 0000000..de917ef
--- /dev/null
+++ b/src/process/ntapi_tt_fork_v1.c
@@ -0,0 +1,218 @@
+/********************************************************/
+/* ntapi: Native API core library */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
+/********************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <ntapi/nt_atomic.h>
+#include <ntapi/nt_status.h>
+#include <ntapi/nt_object.h>
+#include <ntapi/nt_memory.h>
+#include <ntapi/nt_thread.h>
+#include <ntapi/nt_process.h>
+#include <ntapi/nt_string.h>
+#include <ntapi/ntapi.h>
+#include "ntapi_impl.h"
+
+intptr_t __cdecl __attr_hidden__ __tt_fork_v1(void);
+uint32_t __fastcall __attr_hidden__ __tt_fork_child_entry_point(uintptr_t saved_regs_stack_pointer);
+uint32_t __fastcall __attr_hidden__ __tt_fork_child_entry_point_adj(uintptr_t saved_regs_stack_pointer);
+
+/** legacy fork chronology:
+ *
+ * parent:
+ * __ntapi_tt_fork ->
+ * __tt_fork ->
+ * __tt_fork_impl ->
+ * return to __tt_fork -->
+ * __ntapi_tt_fork
+ * -> return to caller
+ *
+ * child:
+ * __tt_fork_child_entry_point[_adj] ->
+ * __ntapi_tt_fork (internal return) ->
+ * -> return to caller
+**/
+
+
+static intptr_t __tt_fork_cancel(void * hprocess,int32_t status)
+{
+ __ntapi->zw_terminate_process(hprocess, status);
+ __ntapi->zw_close(hprocess);
+ return (intptr_t)(-1);
+}
+
+intptr_t __fastcall __tt_fork_impl_v1(
+ uintptr_t saved_regs_stack_pointer,
+ uintptr_t stack_adjustment)
+{
+ int32_t status;
+ void * hprocess;
+ void * hthread;
+ void ** hport_session;
+ ntapi_internals * __internals;
+
+ nt_object_attributes oa;
+ nt_process_basic_information pbi;
+ nt_thread_context context;
+ nt_user_stack stack;
+ nt_memory_basic_information mbi;
+ nt_client_id cid;
+ nt_large_integer timeout;
+
+ hprocess = hthread = (void *)0;
+
+ oa.len = sizeof(nt_object_attributes);
+ oa.root_dir = 0;
+ oa.obj_name = 0;
+ oa.obj_attr = 0;
+ oa.sec_desc = 0;
+ oa.sec_qos = 0;
+
+ if ((status = __ntapi->zw_create_process(
+ &hprocess,
+ NT_PROCESS_ALL_ACCESS,
+ &oa,
+ NT_CURRENT_PROCESS_HANDLE,
+ 1,0,0,0)))
+ return (intptr_t)(-1);
+
+ if ((status = __ntapi->zw_query_information_process(
+ hprocess,
+ NT_PROCESS_BASIC_INFORMATION,
+ (void *)&pbi,
+ sizeof(nt_process_basic_information),
+ 0)))
+ return __tt_fork_cancel(hprocess,status);
+
+
+
+ __ntapi->tt_aligned_block_memset(
+ &context,0,sizeof(nt_thread_context));
+
+ __INIT_CONTEXT(context);
+ context.STACK_POINTER_REGISTER = saved_regs_stack_pointer;
+ context.FAST_CALL_ARG0 = saved_regs_stack_pointer;
+
+ context.INSTRUCTION_POINTER_REGISTER = stack_adjustment
+ ? (uintptr_t)__tt_fork_child_entry_point_adj
+ : (uintptr_t)__tt_fork_child_entry_point;
+
+
+
+ if ((status = __ntapi->zw_query_virtual_memory(
+ NT_CURRENT_PROCESS_HANDLE,
+ (void *)context.STACK_POINTER_REGISTER,
+ NT_MEMORY_BASIC_INFORMATION,
+ &mbi,sizeof(nt_memory_basic_information),0)))
+ return __tt_fork_cancel(hprocess,status);
+
+ stack.fixed_stack_base = (void *)0;
+ stack.fixed_stack_limit = (void *)0;
+ stack.expandable_stack_base = (void *)((uintptr_t)mbi.base_address + mbi.region_size);
+ stack.expandable_stack_limit = (void *)mbi.base_address;
+ stack.expandable_stack_bottom = (void *)mbi.allocation_base;
+
+
+
+ __internals = __ntapi_internals();
+ hport_session = &__internals->hport_tty_session;
+ timeout.quad = (-1) * 10 * 1000 * __NT_FORK_CHILD_WAIT_MILLISEC;
+
+ if (hport_session && *hport_session)
+ if ((status = __ntapi->tty_client_process_register(
+ *hport_session,
+ pbi.unique_process_id,
+ 0, 0, &timeout)))
+ return __tt_fork_cancel(hprocess,status);
+
+
+ if ((status = __ntapi->zw_create_thread(
+ &hthread,
+ NT_THREAD_ALL_ACCESS,
+ &oa,hprocess,&cid,
+ &context,&stack,0)))
+ return __tt_fork_cancel(hprocess,status);
+
+
+ if (cid.process_id > 0) {
+ __internals->hany[0] = hprocess;
+ __internals->hany[1] = hthread;
+ } else {
+ __internals->hany[0] = 0;
+ __internals->hany[1] = 0;
+ }
+
+ /* hoppla */
+ return (int32_t)cid.process_id;
+}
+
+intptr_t __fastcall __ntapi_tt_fork_v1(
+ __out void ** hprocess,
+ __out void ** hthread)
+{
+ int32_t status;
+ intptr_t pid;
+ nt_large_integer timeout;
+ void ** hport_session;
+ void * hevent_tty_connected;
+ ntapi_internals * __internals;
+
+ __internals = __ntapi_internals();
+ hport_session = &__internals->hport_tty_session;
+ timeout.quad = (-1) * 10 * 1000 * __NT_FORK_CHILD_WAIT_MILLISEC;
+
+ if (at_locked_cas(&__internals->hlock,0,1))
+ return (intptr_t)(-1);
+
+ if (hport_session && *hport_session)
+ if (__ntapi_tt_create_inheritable_event(
+ &hevent_tty_connected,
+ NT_NOTIFICATION_EVENT,
+ NT_EVENT_NOT_SIGNALED))
+ return (intptr_t)(-1);
+
+ pid = __tt_fork_v1();
+
+ *hprocess = __internals->hany[0];
+ *hthread = __internals->hany[1];
+
+ at_store(&__internals->hlock,0);
+
+ if (hport_session && *hport_session) {
+ if (pid == 0) {
+ if ((status = __ntapi->tty_connect(
+ hport_session,
+ __internals->subsystem->base_named_objects,
+ NT_SECURITY_IMPERSONATION)))
+ return __tt_fork_cancel(NT_CURRENT_PROCESS_HANDLE,status);
+
+ __internals->hdev_mount_point_mgr = 0;
+
+ if (__internals->rtdata)
+ __internals->rtdata->hsession = *hport_session;
+
+ __ntapi->zw_set_event(
+ hevent_tty_connected,
+ 0);
+
+ } else if (pid > 0) {
+ status = __ntapi->zw_wait_for_single_object(
+ hevent_tty_connected,
+ NT_SYNC_NON_ALERTABLE,
+ &timeout);
+
+ if (status && __PSX_DEBUG)
+ if ((status = __ntapi->zw_wait_for_single_object(
+ hevent_tty_connected,
+ NT_SYNC_NON_ALERTABLE,
+ 0)))
+ pid = __tt_fork_cancel(*hprocess,status);
+ }
+
+ __ntapi->zw_close(hevent_tty_connected);
+ }
+
+ return pid;
+}