summaryrefslogtreecommitdiffhomepage
path: root/src/process
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
parentdcdadc2702712fa750ed255ed1dfa354522797a0 (diff)
downloadntapi-dd89bb8ad4fe184a34b5dbdda237e640fc82121b.tar.bz2
ntapi-dd89bb8ad4fe184a34b5dbdda237e640fc82121b.tar.xz
entered advanced internal development stage.
Diffstat (limited to 'src/process')
-rw-r--r--src/process/nt32/tt_fork_v1.s60
-rw-r--r--src/process/nt32/tt_fork_v1_i386.c66
-rw-r--r--src/process/nt64/tt_fork_v1.s134
-rw-r--r--src/process/nt64/tt_fork_v1_x86_64.asm136
-rw-r--r--src/process/nt64/tt_fork_v2_x86_64.asm50
-rw-r--r--src/process/ntapi_tt_create_native_process_v1.c258
-rw-r--r--src/process/ntapi_tt_create_native_process_v2.c233
-rw-r--r--src/process/ntapi_tt_create_remote_process_params.c331
-rw-r--r--src/process/ntapi_tt_create_remote_runtime_data.c178
-rw-r--r--src/process/ntapi_tt_fork_v1.c218
-rw-r--r--src/process/ntapi_tt_fork_v2.c183
-rw-r--r--src/process/ntapi_tt_get_runtime_data.c83
-rw-r--r--src/process/ntapi_tt_init_runtime_data.c82
-rw-r--r--src/process/ntapi_tt_map_image_as_data.c120
-rw-r--r--src/process/tt_fork_v1.c0
15 files changed, 2132 insertions, 0 deletions
diff --git a/src/process/nt32/tt_fork_v1.s b/src/process/nt32/tt_fork_v1.s
new file mode 100644
index 0000000..2e2f01d
--- /dev/null
+++ b/src/process/nt32/tt_fork_v1.s
@@ -0,0 +1,60 @@
+##########################################################
+## ntapi: Native API core library ##
+## Copyright (C) 2013,2014,2015 Z. Gilboa ##
+## Released under GPLv2 and GPLv3; see COPYING.NTAPI. ##
+##########################################################
+
+.section .text
+
+.global ___tt_fork
+.global ___tt_fork_child_entry_point
+.global @__tt_fork_child_entry_point@4
+.global ___tt_fork_child_entry_point_adj
+.global @__tt_fork_child_entry_point_adj@4
+
+___tt_fork:
+___tt_fork_prolog:
+ push %ebp
+ mov %esp, %ebp
+
+___tt_fork_save_regs:
+ push %ecx
+ push %edx
+ push %ebx
+ push %esi
+ push %edi
+
+___tt_fork_impl_call:
+ mov %esp, %ecx
+ mov $0, %edx
+ call @__tt_fork_impl@8
+
+___tt_fork_restore_regs:
+ pop %edi
+ pop %esi
+ pop %ebx
+ pop %edx
+ pop %ecx
+
+___tt_fork_epilog:
+ mov %ebp, %esp
+ pop %ebp
+ ret
+
+___tt_fork_child_entry_point:
+@__tt_fork_child_entry_point@4:
+___tt_fork_child_entry_point_adj:
+@__tt_fork_child_entry_point_adj@4:
+ xor %eax, %eax
+ mov %ecx, %esp
+
+___tt_fork_child_restore_regs:
+ pop %edi
+ pop %esi
+ pop %ebx
+ pop %edx
+ pop %ecx
+
+___tt_fork_child_epilog:
+ pop %ebp
+ ret
diff --git a/src/process/nt32/tt_fork_v1_i386.c b/src/process/nt32/tt_fork_v1_i386.c
new file mode 100644
index 0000000..34b813e
--- /dev/null
+++ b/src/process/nt32/tt_fork_v1_i386.c
@@ -0,0 +1,66 @@
+/********************************************************/
+/* ntapi: Native API core library */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
+/********************************************************/
+
+#include <psxtypes/psxtypes.h>
+
+#if (__COMPILER__ == __MSVC__) && defined(__X86_MODEL)
+
+intptr_t __fastcall __tt_fork_impl(
+ __in uintptr_t saved_regs_stack_pointer,
+ __in uintptr_t stack_adjustment);
+
+int32_t __declspec(naked) __cdecl __tt_fork(void)
+{
+ __asm {
+ push ebp
+ mov ebp, esp
+
+ push ecx
+ push edx
+ push ebx
+ push esi
+ push edi
+
+ mov ecx, esp
+ call __tt_fork_impl
+
+ pop edi
+ pop esi
+ pop ebx
+ pop edx
+ pop ecx
+
+ mov esp, ebp
+ pop ebp
+ ret
+ };
+}
+
+void __declspec(naked) __fastcall __tt_fork_child_entry_point(uintptr_t esp_saved)
+{
+ __asm {
+ xor eax, eax
+ mov esp, ecx
+
+ pop edi
+ pop esi
+ pop ebx
+ pop edx
+ pop ecx
+
+ pop ebp
+ ret
+ };
+}
+
+void __declspec(naked) __fastcall __tt_fork_child_entry_point_adj(uintptr_t esp_saved)
+{
+ __asm {
+ jmp __tt_fork_child_entry_point
+ };
+}
+
+#endif
diff --git a/src/process/nt64/tt_fork_v1.s b/src/process/nt64/tt_fork_v1.s
new file mode 100644
index 0000000..5f09463
--- /dev/null
+++ b/src/process/nt64/tt_fork_v1.s
@@ -0,0 +1,134 @@
+##########################################################
+## ntapi: Native API core library ##
+## Copyright (C) 2013,2014,2015 Z. Gilboa ##
+## Released under GPLv2 and GPLv3; see COPYING.NTAPI. ##
+##########################################################
+
+.section .text
+
+.global __tt_fork_v1
+.global __tt_fork_child_entry_point
+.global __tt_fork_child_entry_point_adj
+
+__tt_fork_v1:
+__tt_fork_save_regs:
+ push %rbp
+ push %rcx
+ push %rdx
+ push %rbx
+ push %rsi
+ push %rdi
+ push %r8
+ push %r9
+ push %r10
+ push %r11
+ push %r12
+ push %r13
+ push %r14
+ push %r15
+
+ sub 0x40,%rsp
+
+ mov %rsp, %rdx
+ and $0xf, %rdx
+ test %rdx, %rdx
+ jne __tt_fork_impl_adj_call
+
+__tt_fork_impl_call:
+ mov %rsp, %rcx
+ call __tt_fork_impl_v1
+
+ add 0x40,%rsp
+
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %r11
+ pop %r10
+ pop %r9
+ pop %r8
+ pop %rdi
+ pop %rsi
+ pop %rbx
+ pop %rdx
+ pop %rcx
+ pop %rbp
+
+ ret
+
+__tt_fork_impl_adj_call:
+ push %rdi
+
+ mov %rsp, %rcx
+ call __tt_fork_impl_v1
+
+ pop %rdi
+
+ add 0x40,%rsp
+
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %r11
+ pop %r10
+ pop %r9
+ pop %r8
+ pop %rdi
+ pop %rsi
+ pop %rbx
+ pop %rdx
+ pop %rcx
+ pop %rbp
+
+ ret
+
+
+__tt_fork_child_entry_point:
+ xor %rax, %rax
+ mov %rcx, %rsp
+
+ add 0x40,%rsp
+
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %r11
+ pop %r10
+ pop %r9
+ pop %r8
+ pop %rdi
+ pop %rsi
+ pop %rbx
+ pop %rdx
+ pop %rcx
+ pop %rbp
+
+ ret
+
+__tt_fork_child_entry_point_adj:
+ xor %rax, %rax
+ mov %rcx, %rsp
+
+ pop %rdi
+
+ add 0x40,%rsp
+
+ pop %r15
+ pop %r14
+ pop %r13
+ pop %r12
+ pop %r11
+ pop %r10
+ pop %r9
+ pop %r8
+ pop %rdi
+ pop %rsi
+ pop %rbx
+ pop %rdx
+ pop %rcx
+ pop %rbp
+
+ ret
diff --git a/src/process/nt64/tt_fork_v1_x86_64.asm b/src/process/nt64/tt_fork_v1_x86_64.asm
new file mode 100644
index 0000000..f79131e
--- /dev/null
+++ b/src/process/nt64/tt_fork_v1_x86_64.asm
@@ -0,0 +1,136 @@
+/********************************************************/
+/* ntapi: Native API core library */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
+/********************************************************/
+
+TITLE tt_fork_x86_64
+
+.data
+__tt_fork_impl_v1 PROTO C
+
+.code
+__tt_fork_v1 PROC
+ push rbp
+ push rcx
+ push rdx
+ push rbx
+ push rsi
+ push rdi
+ push r8
+ push r9
+ push r10
+ push r11
+ push r12
+ push r13
+ push r14
+ push r15
+
+ sub rsp, 40h
+
+ mov rdx, rsp
+ and rdx, 15
+ test rdx, rdx
+ jne __tt_fork_impl_adj_call
+
+ mov rcx, rsp
+ call __tt_fork_impl_v1
+
+ add rsp, 40h
+
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ pop r11
+ pop r10
+ pop r9
+ pop r8
+ pop rdi
+ pop rsi
+ pop rbx
+ pop rdx
+ pop rcx
+ pop rbp
+ ret
+__tt_fork_v1 ENDP
+
+__tt_fork_impl_adj_call PROC
+ push rdi
+
+ mov rcx, rsp
+ mov rdx, 1
+ call __tt_fork_impl_v1
+
+ pop rdi
+
+ add rsp, 40h
+
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ pop r11
+ pop r10
+ pop r9
+ pop r8
+ pop rdi
+ pop rsi
+ pop rbx
+ pop rdx
+ pop rcx
+ pop rbp
+ ret
+__tt_fork_impl_adj_call ENDP
+
+
+__tt_fork_child_entry_point PROC
+ xor rax, rax
+ mov rsp, rcx
+
+ add rsp, 40h
+
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ pop r11
+ pop r10
+ pop r9
+ pop r8
+ pop rdi
+ pop rsi
+ pop rbx
+ pop rdx
+ pop rcx
+ pop rbp
+ ret
+__tt_fork_child_entry_point ENDP
+
+
+__tt_fork_child_entry_point_adj PROC
+ xor rax, rax
+ mov rsp, rcx
+
+ pop rdi
+
+ add rsp, 40h
+
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ pop r11
+ pop r10
+ pop r9
+ pop r8
+ pop rdi
+ pop rsi
+ pop rbx
+ pop rdx
+ pop rcx
+ pop rbp
+ ret
+__tt_fork_child_entry_point_adj ENDP
+
+END
diff --git a/src/process/nt64/tt_fork_v2_x86_64.asm b/src/process/nt64/tt_fork_v2_x86_64.asm
new file mode 100644
index 0000000..cc6e353
--- /dev/null
+++ b/src/process/nt64/tt_fork_v2_x86_64.asm
@@ -0,0 +1,50 @@
+/********************************************************/
+/* ntapi: Native API core library */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
+/********************************************************/
+
+TITLE tt_fork_x86_64
+
+.data
+__tt_fork_impl_v2 PROTO C
+
+.code
+__tt_fork_v2 PROC
+ push rbp
+ push rcx
+ push rdx
+ push rbx
+ push rsi
+ push rdi
+ push r8
+ push r9
+ push r10
+ push r11
+ push r12
+ push r13
+ push r14
+ push r15
+
+ sub rsp, 40h
+ call __tt_fork_impl_v2
+ add rsp, 40h
+
+ pop r15
+ pop r14
+ pop r13
+ pop r12
+ pop r11
+ pop r10
+ pop r9
+ pop r8
+ pop rdi
+ pop rsi
+ pop rbx
+ pop rdx
+ pop rcx
+ pop rbp
+ ret
+__tt_fork_v2 ENDP
+
+END
diff --git a/src/process/ntapi_tt_create_native_process_v1.c b/src/process/ntapi_tt_create_native_process_v1.c
new file mode 100644
index 0000000..b2572cc
--- /dev/null
+++ b/src/process/ntapi_tt_create_native_process_v1.c
@@ -0,0 +1,258 @@
+/********************************************************/
+/* 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 <pemagine/pemagine.h>
+#include <ntapi/nt_status.h>
+#include <ntapi/nt_object.h>
+#include <ntapi/nt_thread.h>
+#include <ntapi/nt_process.h>
+#include <ntapi/nt_string.h>
+#include <ntapi/ntapi.h>
+#include "ntapi_impl.h"
+
+static int32_t __tt_create_process_cancel(nt_create_process_params * params, void * hsection, int32_t status)
+{
+ if (params->hprocess) {
+ __ntapi->zw_terminate_process(params->hprocess,NT_STATUS_INTERNAL_ERROR);
+ __ntapi->zw_close(params->hprocess);
+ }
+
+ if (params->hthread)
+ __ntapi->zw_close(params->hthread);
+
+ if (hsection)
+ __ntapi->zw_close(hsection);
+
+ return status;
+}
+
+int32_t __stdcall __ntapi_tt_create_native_process_v1(nt_create_process_params * params)
+{
+ int32_t status;
+ void * hfile;
+ void * hsection;
+
+ nt_object_attributes oa_file;
+ nt_object_attributes oa_process;
+ nt_object_attributes oa_thread;
+
+ nt_unicode_string nt_image;
+ nt_unicode_string nt_cmd_line;
+ nt_process_parameters * rprocess_params;
+ nt_thread_params tparams;
+
+ nt_io_status_block iosb;
+ nt_section_image_information sii;
+
+ wchar16_t * cmd_line_runtime_buffer;
+ size_t cmd_line_runtime_buffer_size;
+ int fresume_thread;
+
+ #if defined (__NT32)
+ wchar16_t runtime_arg[12] = {
+ ' ','-','r',' ',
+ 'i','n','t','e','g','r','a','l'};
+ #elif defined (__NT64)
+ wchar16_t runtime_arg[20] = {
+ ' ','-','r',' ',
+ 'i','n','t','e','g','r','a','l',
+ '-','r','u','n','t','i','m','e'};
+ #endif
+
+ /* validation */
+ if (params->cmd_line && params->process_params)
+ return NT_STATUS_INVALID_PARAMETER_MIX;
+ else if (params->cmd_line && params->rtblock)
+ return NT_STATUS_INVALID_PARAMETER_MIX;
+ else if (params->environment && params->process_params)
+ return NT_STATUS_INVALID_PARAMETER_MIX;
+
+ /* tparams */
+ __ntapi->tt_aligned_block_memset(
+ &tparams, 0, sizeof(tparams));
+
+ /* image_name */
+ __ntapi->rtl_init_unicode_string(
+ &nt_image,
+ params->image_name);
+
+ /* oa_process */
+ if (!params->obj_attr_process) {
+ __ntapi->tt_aligned_block_memset(
+ &oa_process,0,sizeof(oa_process));
+
+ oa_process.len = sizeof(oa_process);
+ params->obj_attr_process = &oa_process;
+ }
+
+ /* oa_thread */
+ if (!params->obj_attr_thread) {
+ __ntapi->tt_aligned_block_memset(
+ &oa_thread,0,sizeof(oa_thread));
+
+ oa_thread.len = sizeof(oa_thread);
+ params->obj_attr_thread = &oa_thread;
+ }
+
+ /* legacy tasks */
+ /* init the oa_file structure */
+ oa_file.len = sizeof(nt_object_attributes);
+ oa_file.root_dir = (void *)0;
+ oa_file.obj_name = &nt_image;
+ oa_file.obj_attr = 0;
+ oa_file.sec_desc = (nt_security_descriptor *)0;
+ oa_file.sec_qos = (nt_sqos *)0;
+
+ /* open the file */
+ if ((status = __ntapi->zw_open_file(
+ &hfile,
+ NT_FILE_EXECUTE | NT_PROCESS_SYNCHRONIZE,
+ &oa_file,
+ &iosb,
+ NT_FILE_SHARE_READ,
+ NT_FILE_SYNCHRONOUS_IO_NONALERT)))
+ return status;
+
+ /* create the executable section */
+ hsection = 0;
+ oa_file.obj_name = 0;
+
+ status = __ntapi->zw_create_section(
+ &hsection,
+ NT_SECTION_ALL_ACCESS,
+ &oa_file,0,
+ NT_PAGE_EXECUTE,
+ NT_SEC_IMAGE,
+ hfile);
+
+ __ntapi->zw_close(hfile);
+ if (status) return status;
+
+ /* create the process */
+ if ((status = __ntapi->zw_create_process(
+ &params->hprocess,
+ NT_PROCESS_ALL_ACCESS,
+ &oa_process,
+ NT_CURRENT_PROCESS_HANDLE,
+ 1,hsection,0,0)))
+ return __tt_create_process_cancel(params,hsection,status);
+
+ /* obtain stack/heap and entry point information */
+ if ((status = __ntapi->zw_query_section(
+ hsection,
+ NT_SECTION_IMAGE_INFORMATION,
+ &sii,sizeof(sii),0)))
+ return __tt_create_process_cancel(params,hsection,status);
+
+ /* obtain process information */
+ if ((status = __ntapi->zw_query_information_process(
+ tparams.hprocess,
+ NT_PROCESS_BASIC_INFORMATION,
+ &params->pbi,sizeof(params->pbi),
+ 0)))
+ return __tt_create_process_cancel(params,hsection,status);
+
+ /* create remote process parameters block */
+ if (!params->process_params) {
+ /* cmd_line */
+ if (!params->cmd_line) {
+ params->cmd_line = params->image_name;
+ }
+
+ __ntapi->rtl_init_unicode_string(
+ &nt_cmd_line,
+ params->cmd_line);
+
+ /* rtblock */
+ if (params->rtblock) {
+ cmd_line_runtime_buffer = (wchar16_t *)0;
+ cmd_line_runtime_buffer_size = nt_cmd_line.maxlen
+ + sizeof(runtime_arg);
+
+ if ((status = __ntapi->zw_allocate_virtual_memory(
+ NT_CURRENT_PROCESS_HANDLE,
+ (void **)&cmd_line_runtime_buffer,
+ 0,&cmd_line_runtime_buffer_size,
+ NT_MEM_RESERVE | NT_MEM_COMMIT,
+ NT_PAGE_READWRITE)))
+ return __tt_create_process_cancel(params,hsection,status);
+
+ __ntapi->tt_memcpy_utf16(
+ (wchar16_t *)cmd_line_runtime_buffer,
+ (wchar16_t *)nt_cmd_line.buffer,
+ nt_cmd_line.strlen);
+
+ __ntapi->tt_memcpy_utf16(
+ (wchar16_t *)pe_va_from_rva(
+ cmd_line_runtime_buffer,
+ nt_cmd_line.strlen),
+ (wchar16_t *)runtime_arg,
+ sizeof(runtime_arg));
+
+ nt_cmd_line.strlen += sizeof(runtime_arg);
+ nt_cmd_line.maxlen += sizeof(runtime_arg);
+ nt_cmd_line.buffer = cmd_line_runtime_buffer;
+ }
+
+ /* environment */
+ if (!params->environment) {
+ params->environment = __ntapi->tt_get_peb_env_block_utf16();
+ }
+ }
+
+ fresume_thread = (params->creation_flags_thread ^ 0x01) & 0x01;
+
+ /* create target thread */
+ tparams.hprocess = params->hprocess;
+ tparams.start = (nt_thread_start_routine *)sii.entry_point;
+ tparams.obj_attr = &oa_thread;
+ tparams.creation_flags = NT_CREATE_SUSPENDED | NT_CREATE_FIRST_THREAD_OF_PROCESS;
+ tparams.stack_size_commit = sii.stack_commit;
+ tparams.stack_size_reserve = sii.stack_reserve;
+
+ if ((status = __ntapi->tt_create_remote_thread(&tparams)))
+ return __tt_create_process_cancel(params,hsection,status);
+
+ /* remote process params */
+ if ((status = __ntapi->tt_create_remote_process_params(
+ tparams.hprocess,
+ &rprocess_params,
+ &nt_image,
+ (nt_unicode_string *)0,
+ (nt_unicode_string *)0,
+ &nt_cmd_line,
+ params->environment,
+ (nt_unicode_string *)0,
+ (nt_unicode_string *)0,
+ (nt_unicode_string *)0,
+ (nt_unicode_string *)0)))
+ return __tt_create_process_cancel(params,hsection,status);
+
+ /* update the target process environment block: */
+ /* make process_params point to rparams_block */
+ if ((status = __ntapi->zw_write_virtual_memory(
+ tparams.hprocess,
+ (char *)((uintptr_t)params->pbi.peb_base_address
+ + (uintptr_t)&(((nt_peb *)0)->process_params)),
+ (char *)&rprocess_params,
+ sizeof(uintptr_t),0)))
+ return __tt_create_process_cancel(params,hsection,status);
+
+ /* rtdata */
+ if (params->rtblock && (status = __ntapi_tt_create_remote_runtime_data(tparams.hprocess,params->rtblock)))
+ return __tt_create_process_cancel(params,hsection,status);
+
+ if (fresume_thread && (status = __ntapi->zw_resume_thread(tparams.hthread,0)))
+ return __tt_create_process_cancel(params,hsection,status);
+
+ /* all done */
+ params->hthread = tparams.hthread;
+ params->cid.process_id = params->pbi.unique_process_id;
+ params->cid.thread_id = tparams.thread_id;
+
+ return status;
+}
diff --git a/src/process/ntapi_tt_create_native_process_v2.c b/src/process/ntapi_tt_create_native_process_v2.c
new file mode 100644
index 0000000..49fbaf7
--- /dev/null
+++ b/src/process/ntapi_tt_create_native_process_v2.c
@@ -0,0 +1,233 @@
+/********************************************************/
+/* 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 <pemagine/pemagine.h>
+#include <ntapi/nt_status.h>
+#include <ntapi/nt_object.h>
+#include <ntapi/nt_thread.h>
+#include <ntapi/nt_process.h>
+#include <ntapi/nt_string.h>
+#include <ntapi/ntapi.h>
+#include "ntapi_impl.h"
+
+static int32_t __tt_create_process_cancel(nt_create_process_params * params, int32_t status)
+{
+ if (params->hprocess) {
+ __ntapi->zw_terminate_process(params->hprocess,NT_STATUS_INTERNAL_ERROR);
+ __ntapi->zw_close(params->hprocess);
+ }
+
+ if (params->hthread)
+ __ntapi->zw_close(params->hthread);
+
+ return status;
+}
+
+
+int32_t __stdcall __ntapi_tt_create_native_process_v2(
+ __in_out nt_create_process_params * params)
+{
+ int32_t status;
+
+ nt_object_attributes oa_process;
+ nt_object_attributes oa_thread;
+
+ nt_unicode_string nt_image;
+ nt_unicode_string nt_cmd_line;
+ wchar16_t * cmd_line_runtime_buffer;
+ size_t cmd_line_runtime_buffer_size;
+
+ nt_create_process_info nt_process_info;
+ int fresume_thread;
+
+ struct {
+ size_t size_in_bytes;
+ nt_create_process_ext_param file_info;
+ } ext_params;
+
+ #if defined (__NT32)
+ wchar16_t runtime_arg[12] = {
+ ' ','-','r',' ',
+ 'i','n','t','e','g','r','a','l'};
+ #elif defined (__NT64)
+ wchar16_t runtime_arg[20] = {
+ ' ','-','r',' ',
+ 'i','n','t','e','g','r','a','l',
+ '-','r','u','n','t','i','m','e'};
+ #endif
+
+ /* validation */
+ if (params->cmd_line && params->process_params)
+ return NT_STATUS_INVALID_PARAMETER_MIX;
+ else if (params->cmd_line && params->rtblock)
+ return NT_STATUS_INVALID_PARAMETER_MIX;
+ else if (params->environment && params->process_params)
+ return NT_STATUS_INVALID_PARAMETER_MIX;
+
+ /* image_name */
+ __ntapi->rtl_init_unicode_string(
+ &nt_image,
+ params->image_name);
+
+ /* oa_process */
+ if (!params->obj_attr_process) {
+ __ntapi->tt_aligned_block_memset(
+ &oa_process,0,sizeof(oa_process));
+
+ oa_process.len = sizeof(oa_process);
+ params->obj_attr_process = &oa_process;
+ }
+
+ /* oa_thread */
+ if (!params->obj_attr_thread) {
+ __ntapi->tt_aligned_block_memset(
+ &oa_thread,0,sizeof(oa_thread));
+
+ oa_thread.len = sizeof(oa_thread);
+ params->obj_attr_thread = &oa_thread;
+ }
+
+ /* process_params */
+ if (!params->process_params) {
+ /* cmd_line */
+ if (!params->cmd_line) {
+ params->cmd_line = params->image_name;
+ }
+
+ __ntapi->rtl_init_unicode_string(
+ &nt_cmd_line,
+ params->cmd_line);
+
+ /* rtdata (alternative to cmd_line) */
+ if (params->rtblock) {
+ cmd_line_runtime_buffer = (wchar16_t *)0;
+ cmd_line_runtime_buffer_size = nt_cmd_line.maxlen
+ + sizeof(runtime_arg);
+
+ if ((status = __ntapi->zw_allocate_virtual_memory(
+ NT_CURRENT_PROCESS_HANDLE,
+ (void **)&cmd_line_runtime_buffer,
+ 0,&cmd_line_runtime_buffer_size,
+ NT_MEM_RESERVE | NT_MEM_COMMIT,
+ NT_PAGE_READWRITE)))
+ return status;
+
+ __ntapi->tt_memcpy_utf16(
+ (wchar16_t *)cmd_line_runtime_buffer,
+ (wchar16_t *)nt_cmd_line.buffer,
+ nt_cmd_line.strlen);
+
+ __ntapi->tt_memcpy_utf16(
+ (wchar16_t *)pe_va_from_rva(
+ cmd_line_runtime_buffer,
+ nt_cmd_line.strlen),
+ (wchar16_t *)runtime_arg,
+ sizeof(runtime_arg));
+
+ nt_cmd_line.strlen += sizeof(runtime_arg);
+ nt_cmd_line.maxlen += sizeof(runtime_arg);
+ nt_cmd_line.buffer = cmd_line_runtime_buffer;
+ }
+
+
+ /* environment */
+ if (!params->environment)
+ params->environment = __ntapi->tt_get_peb_env_block_utf16();
+
+ if ((status = __ntapi->rtl_create_process_parameters(
+ &params->process_params,
+ &nt_image,
+ (nt_unicode_string *)0,
+ (nt_unicode_string *)0,
+ &nt_cmd_line,
+ params->environment,
+ (nt_unicode_string *)0,
+ (nt_unicode_string *)0,
+ (nt_unicode_string *)0,
+ (nt_unicode_string *)0)))
+ return status;
+
+ __ntapi->rtl_normalize_process_params(params->process_params);
+ }
+
+ /* create_process_info */
+ if (!params->create_process_info) {
+ __ntapi->tt_aligned_block_memset(
+ &nt_process_info,0,sizeof(nt_process_info));
+
+ nt_process_info.size = sizeof(nt_create_process_info);
+ nt_process_info.state = NT_PROCESS_CREATE_INITIAL_STATE;
+ nt_process_info.init_state.init_flags = NT_PROCESS_CREATE_INFO_OBTAIN_OUTPUT;
+ nt_process_info.init_state.file_access_ext = NT_FILE_READ_ATTRIBUTES|NT_FILE_READ_ACCESS;
+
+ params->create_process_info = &nt_process_info;
+ }
+
+ /* create_process_ext_params */
+ if (!params->create_process_ext_params) {
+ __ntapi->tt_aligned_block_memset(
+ &ext_params,0,sizeof(ext_params));
+
+ ext_params.size_in_bytes = sizeof(ext_params);
+
+ /* file_info */
+ ext_params.file_info.ext_param_type = NT_CREATE_PROCESS_EXT_PARAM_SET_FILE_NAME;
+ ext_params.file_info.ext_param_size = nt_image.strlen;
+ ext_params.file_info.ext_param_addr = nt_image.buffer;
+
+ params->create_process_ext_params = (nt_create_process_ext_params *)&ext_params;
+ }
+
+ params->hprocess = 0;
+ params->hthread = 0;
+ fresume_thread = 0;
+
+ if (params->rtblock) {
+ fresume_thread = (params->creation_flags_thread ^ 0x01) & 0x01;
+ params->creation_flags_thread |= 0x01;
+ }
+
+ if (!params->desired_access_process)
+ params->desired_access_process = NT_PROCESS_ALL_ACCESS;
+
+ if (!params->desired_access_thread)
+ params->desired_access_thread = NT_THREAD_ALL_ACCESS;
+
+ if ((status = __ntapi->zw_create_user_process(
+ &params->hprocess,
+ &params->hthread,
+ params->desired_access_process,
+ params->desired_access_thread,
+ params->obj_attr_process,
+ params->obj_attr_thread,
+ params->creation_flags_process,
+ params->creation_flags_thread,
+ params->process_params,
+ params->create_process_info,
+ params->create_process_ext_params)))
+ return status;
+
+ if ((status = __ntapi->zw_query_information_process(
+ params->hprocess,
+ NT_PROCESS_BASIC_INFORMATION,
+ &params->pbi,sizeof(params->pbi),
+ 0)))
+ return __tt_create_process_cancel(params,status);
+
+ if (!params->rtblock)
+ return NT_STATUS_SUCCESS;
+
+ /* rtdata */
+ if ((status = __ntapi_tt_create_remote_runtime_data(params->hprocess,params->rtblock)))
+ return __tt_create_process_cancel(params,status);
+
+ /* conditional resume */
+ if (fresume_thread && (status = __ntapi->zw_resume_thread(params->hthread,0)))
+ return __tt_create_process_cancel(params,status);
+
+ return NT_STATUS_SUCCESS;
+}
diff --git a/src/process/ntapi_tt_create_remote_process_params.c b/src/process/ntapi_tt_create_remote_process_params.c
new file mode 100644
index 0000000..3ff8711
--- /dev/null
+++ b/src/process/ntapi_tt_create_remote_process_params.c
@@ -0,0 +1,331 @@
+/********************************************************/
+/* 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 <pemagine/pemagine.h>
+#include <ntapi/nt_status.h>
+#include <ntapi/nt_object.h>
+#include <ntapi/nt_thread.h>
+#include <ntapi/nt_process.h>
+#include <ntapi/nt_string.h>
+#include <ntapi/ntapi.h>
+#include "ntapi_impl.h"
+
+int32_t __stdcall __ntapi_tt_create_remote_process_params(
+ __in void * hprocess,
+ __out nt_process_parameters ** rprocess_params,
+ __in nt_unicode_string * image_file,
+ __in nt_unicode_string * dll_path __optional,
+ __in nt_unicode_string * current_directory __optional,
+ __in nt_unicode_string * command_line __optional,
+ __in wchar16_t * environment __optional,
+ __in nt_unicode_string * window_title __optional,
+ __in nt_unicode_string * desktop_info __optional,
+ __in nt_unicode_string * shell_info __optional,
+ __in nt_unicode_string * runtime_data __optional)
+{
+ #define __ALIGN_ALLOC_SIZE \
+ process_params.alloc_size += sizeof(uintptr_t) - 1; \
+ process_params.alloc_size /= sizeof(uintptr_t); \
+ process_params.alloc_size *= sizeof(uintptr_t);
+
+ int32_t status;
+
+ ptrdiff_t d_image;
+ ptrdiff_t d_dll_path;
+ ptrdiff_t d_cwd;
+ ptrdiff_t d_cmd_line;
+ ptrdiff_t d_environment;
+ ptrdiff_t d_runtime;
+ /*
+ ptrdiff_t d_wnd_title;
+ ptrdiff_t d_desktop;
+ ptrdiff_t d_shell;
+ */
+
+ wchar16_t * wch;
+ size_t env_block_size;
+ size_t params_block_size;
+ size_t bytes_written;
+
+ nt_process_parameters process_params;
+ nt_process_parameters * params_block;
+ nt_process_parameters * rparams_block;
+ nt_process_parameters * params_default;
+
+ /* make the compiler happy */
+ d_image = 0;
+ d_dll_path = 0;
+ d_cwd = 0;
+ d_cmd_line = 0;
+ d_environment = 0;
+ d_runtime = 0;
+ env_block_size = 0;
+
+ /* initialize */
+ __ntapi->tt_aligned_block_memset(
+ &process_params,
+ 0,sizeof(nt_process_parameters));
+
+ /* allow for extended structures (newer OS versions) */
+ process_params.alloc_size = sizeof(nt_process_parameters)
+ + 8 * sizeof(uintptr_t);
+
+ params_default = ((nt_peb *)pe_get_peb_address())->process_params;
+
+ /* image_file */
+ if (image_file) {
+ /* check alignment and sanity */
+ if ((uintptr_t)image_file->buffer % sizeof(uintptr_t))
+ return NT_STATUS_INVALID_PARAMETER_2;
+ else if (image_file->maxlen < image_file->strlen)
+ return NT_STATUS_INVALID_PARAMETER_2;
+
+ process_params.image_file_name.strlen = image_file->strlen;
+ process_params.image_file_name.maxlen = image_file->maxlen;
+
+ /* store offset and update alloc_size */
+ d_image = process_params.alloc_size;
+ process_params.alloc_size += image_file->maxlen;
+ __ALIGN_ALLOC_SIZE;
+ }
+
+ /* dll_path */
+ if (!dll_path)
+ dll_path = &(params_default->dll_path);
+
+ if (dll_path) {
+ /* check alignment and sanity */
+ if ((uintptr_t)dll_path->buffer % sizeof(uintptr_t))
+ return NT_STATUS_INVALID_PARAMETER_3;
+ else if (dll_path->maxlen < dll_path->strlen)
+ return NT_STATUS_INVALID_PARAMETER_3;
+
+ process_params.dll_path.strlen = dll_path->strlen;
+ process_params.dll_path.maxlen = dll_path->maxlen;
+
+ /* store offset and update alloc_size */
+ d_dll_path = process_params.alloc_size;
+ process_params.alloc_size += dll_path->maxlen;
+ __ALIGN_ALLOC_SIZE;
+ }
+
+ /* current_directory */
+ if (!current_directory)
+ current_directory = &(params_default->cwd_name);
+
+ if (current_directory) {
+ /* check alignment and sanity */
+ if ((uintptr_t)current_directory->buffer % sizeof(uintptr_t))
+ return NT_STATUS_INVALID_PARAMETER_4;
+ else if (current_directory->maxlen < current_directory->strlen)
+ return NT_STATUS_INVALID_PARAMETER_4;
+
+ process_params.cwd_name.strlen = current_directory->strlen;
+ process_params.cwd_name.maxlen = current_directory->maxlen;
+
+ /* store offset and update alloc_size */
+ d_cwd = process_params.alloc_size;
+ process_params.alloc_size += current_directory->maxlen;
+ __ALIGN_ALLOC_SIZE;
+ }
+
+ /* command_line */
+ if (command_line) {
+ /* check alignment and sanity */
+ if ((uintptr_t)command_line->buffer % sizeof(uintptr_t))
+ return NT_STATUS_INVALID_PARAMETER_5;
+ else if (command_line->maxlen < command_line->strlen)
+ return NT_STATUS_INVALID_PARAMETER_5;
+
+ process_params.command_line.strlen = command_line->strlen;
+ process_params.command_line.maxlen = command_line->maxlen;
+
+ /* store offset and update alloc_size */
+ d_cmd_line = process_params.alloc_size;
+ process_params.alloc_size += command_line->maxlen;
+ __ALIGN_ALLOC_SIZE;
+ }
+
+ /* environment */
+ if (environment) {
+ /* check alignment */
+ if ((uintptr_t)environment % sizeof(uintptr_t))
+ return NT_STATUS_INVALID_PARAMETER_6;
+
+ /* obtain size of environment block */
+ wch = environment;
+
+ while (*wch) {
+ /* reach the end of the current variable */
+ while (*wch++)
+ /* proceed to the next variable */
+ wch++;
+ }
+
+ env_block_size = (uintptr_t)wch - (uintptr_t)environment;
+
+ /* store offset and update alloc_size */
+ d_environment = process_params.alloc_size;
+ process_params.alloc_size += (uint32_t)env_block_size + 0x1000;
+ __ALIGN_ALLOC_SIZE;
+ }
+
+ /* runtime_data */
+ if (runtime_data) {
+ /* check alignment and sanity */
+ if ((uintptr_t)runtime_data->buffer % sizeof(uintptr_t))
+ return NT_STATUS_INVALID_PARAMETER_5;
+ else if (runtime_data->maxlen < runtime_data->strlen)
+ return NT_STATUS_INVALID_PARAMETER_5;
+
+ process_params.runtime_data.strlen = runtime_data->strlen;
+ process_params.runtime_data.maxlen = runtime_data->maxlen;
+
+ /* store offset and update alloc_size */
+ d_runtime = process_params.alloc_size;
+ process_params.alloc_size += runtime_data->maxlen;
+ __ALIGN_ALLOC_SIZE;
+ }
+
+ /* allocate local and remote process parameters blocks */
+ params_block = (nt_process_parameters *)0;
+ rparams_block = (nt_process_parameters *)0;
+
+ process_params.used_size = process_params.alloc_size;
+ params_block_size = process_params.alloc_size;
+
+ /* local block */
+ status = __ntapi->zw_allocate_virtual_memory(
+ NT_CURRENT_PROCESS_HANDLE,
+ (void **)&params_block,
+ 0,
+ &params_block_size,
+ NT_MEM_COMMIT,
+ NT_PAGE_READWRITE);
+
+ if (status != NT_STATUS_SUCCESS)
+ return status;
+
+ process_params.alloc_size = (uint32_t)params_block_size;
+ __ntapi->tt_aligned_block_memset(params_block,0,params_block_size);
+
+ /* remote block */
+ status = __ntapi->zw_allocate_virtual_memory(
+ hprocess,
+ (void **)&rparams_block,
+ 0,
+ &params_block_size,
+ NT_MEM_RESERVE | NT_MEM_COMMIT,
+ NT_PAGE_READWRITE);
+
+ if (status != NT_STATUS_SUCCESS) {
+ __ntapi->zw_free_virtual_memory(
+ NT_CURRENT_PROCESS_HANDLE,
+ (void **)&params_block,
+ (size_t *)&process_params.alloc_size,
+ NT_MEM_RELEASE);
+
+ return status;
+ }
+
+ /* copy the process_params structure */
+ __ntapi->tt_aligned_memcpy_utf16(
+ (uintptr_t *)params_block,
+ (uintptr_t *)&process_params,
+ sizeof(nt_process_parameters));
+
+ /* image_file */
+ if (image_file) {
+ params_block->image_file_name.buffer =
+ (uint16_t *)pe_va_from_rva(rparams_block,d_image);
+
+ __ntapi->tt_aligned_memcpy_utf16(
+ (uintptr_t *)pe_va_from_rva(params_block,d_image),
+ (uintptr_t *)image_file->buffer,
+ image_file->strlen);
+ }
+
+ /* dll_path */
+ if (dll_path) {
+ params_block->dll_path.buffer =
+ (uint16_t *)pe_va_from_rva(rparams_block,d_dll_path);
+
+ __ntapi->tt_aligned_memcpy_utf16(
+ (uintptr_t *)pe_va_from_rva(params_block,d_dll_path),
+ (uintptr_t *)dll_path->buffer,
+ dll_path->strlen);
+ }
+
+ /* current_directory */
+ if (current_directory) {
+ params_block->cwd_name.buffer =
+ (uint16_t *)pe_va_from_rva(rparams_block,d_cwd);
+
+ __ntapi->tt_aligned_memcpy_utf16(
+ (uintptr_t *)pe_va_from_rva(params_block,d_cwd),
+ (uintptr_t *)current_directory->buffer,
+ current_directory->strlen);
+ }
+
+ /* command_line */
+ if (command_line) {
+ params_block->command_line.buffer =
+ (uint16_t *)pe_va_from_rva(rparams_block,d_cmd_line);
+
+ __ntapi->tt_aligned_memcpy_utf16(
+ (uintptr_t *)pe_va_from_rva(params_block,d_cmd_line),
+ (uintptr_t *)command_line->buffer,
+ command_line->strlen);
+ }
+
+ /* environment */
+ if (environment) {
+ params_block->environment =
+ (wchar16_t *)pe_va_from_rva(rparams_block,d_environment);
+
+ __ntapi->tt_aligned_memcpy_utf16(
+ (uintptr_t *)pe_va_from_rva(params_block,d_environment),
+ (uintptr_t *)environment,
+ env_block_size);
+ }
+
+ /* runtime_data */
+ if (runtime_data) {
+ params_block->runtime_data.buffer =
+ (uint16_t *)pe_va_from_rva(rparams_block,d_runtime);
+
+ __ntapi->tt_aligned_memcpy_utf16(
+ (uintptr_t *)pe_va_from_rva(params_block,d_runtime),
+ (uintptr_t *)runtime_data->buffer,
+ runtime_data->strlen);
+ }
+
+ params_block->flags = 1; /* normalized */
+
+ /* copy the local params block to the remote process */
+ status = __ntapi->zw_write_virtual_memory(
+ hprocess,
+ rparams_block,
+ (char *)params_block,
+ process_params.alloc_size,
+ &bytes_written);
+
+ if (status != NT_STATUS_SUCCESS)
+ return status;
+
+ /* free the local params block */
+ __ntapi->zw_free_virtual_memory(
+ NT_CURRENT_PROCESS_HANDLE,
+ (void **)&params_block,
+ (size_t *)&process_params.alloc_size,
+ NT_MEM_RELEASE);
+
+ /* all done */
+ *rprocess_params = rparams_block;
+
+ return NT_STATUS_SUCCESS;
+}
diff --git a/src/process/ntapi_tt_create_remote_runtime_data.c b/src/process/ntapi_tt_create_remote_runtime_data.c
new file mode 100644
index 0000000..d3cf9ca
--- /dev/null
+++ b/src/process/ntapi_tt_create_remote_runtime_data.c
@@ -0,0 +1,178 @@
+/********************************************************/
+/* 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_memory.h>
+#include <ntapi/nt_process.h>
+#include <ntapi/ntapi.h>
+#include "ntapi_impl.h"
+
+typedef struct _nt_process_basic_information nt_pbi;
+
+int32_t __stdcall __ntapi_tt_create_remote_runtime_data(
+ __in void * hprocess,
+ __in_out nt_runtime_data_block * rtblock)
+{
+ int32_t status;
+
+ size_t bytes_written;
+ nt_pbi rpbi;
+ nt_process_parameters * rprocess_params;
+ nt_unicode_string rcmd_line;
+ uint32_t runtime_arg_hash;
+ nt_runtime_data * rtdata;
+ void * srv_ready;
+
+ #if defined (__NT32)
+ wchar16_t runtime_arg[8] = {
+ 'i','n','t','e','g','r','a','l'};
+ #elif defined (__NT64)
+ wchar16_t runtime_arg[16] = {
+ 'i','n','t','e','g','r','a','l',
+ '-','r','u','n','t','i','m','e'};
+ #endif
+
+ /* validation */
+ if (!hprocess)
+ return NT_STATUS_INVALID_PARAMETER_1;
+ else if (!rtblock)
+ return NT_STATUS_INVALID_PARAMETER_2;
+ else if (!rtblock->addr)
+ return NT_STATUS_INVALID_PARAMETER_2;
+ else if (!rtblock->size)
+ return NT_STATUS_INVALID_PARAMETER_2;
+
+ runtime_arg_hash = __ntapi->tt_buffer_crc32(
+ 0,
+ (char *)runtime_arg,
+ sizeof(runtime_arg));
+
+ /* obtain process information */
+ status = __ntapi->zw_query_information_process(
+ hprocess,
+ NT_PROCESS_BASIC_INFORMATION,
+ (void *)&rpbi,
+ sizeof(nt_process_basic_information),
+ 0);
+
+ if (status != NT_STATUS_SUCCESS)
+ return status;
+
+ status = __ntapi->zw_read_virtual_memory(
+ hprocess,
+ pe_va_from_rva(
+ rpbi.peb_base_address,
+ (uintptr_t)&(((nt_peb *)0)->process_params)),
+ (char *)&rprocess_params,
+ sizeof(uintptr_t),
+ &bytes_written);
+
+ if (status != NT_STATUS_SUCCESS)
+ return status;
+
+ status = __ntapi->zw_read_virtual_memory(
+ hprocess,
+ &rprocess_params->command_line,
+ (char *)&rcmd_line,
+ sizeof(nt_unicode_string),
+ &bytes_written);
+
+ if (status != NT_STATUS_SUCCESS)
+ return status;
+
+ if (rcmd_line.buffer == 0)
+ return NT_STATUS_BUFFER_TOO_SMALL;
+ else if (rcmd_line.strlen < sizeof(runtime_arg) + 4*sizeof(wchar16_t))
+ return NT_STATUS_INVALID_USER_BUFFER;
+
+ status = __ntapi->zw_read_virtual_memory(
+ hprocess,
+ pe_va_from_rva(
+ rcmd_line.buffer,
+ rcmd_line.strlen - sizeof(runtime_arg)),
+ (char *)&runtime_arg,
+ sizeof(runtime_arg),
+ &bytes_written);
+
+ if (status != NT_STATUS_SUCCESS)
+ return status;
+
+ /* verify remote process compatibility */
+ runtime_arg_hash ^= __ntapi->tt_buffer_crc32(
+ 0,
+ (char *)runtime_arg,
+ sizeof(runtime_arg));
+
+ if (runtime_arg_hash)
+ return NT_STATUS_INVALID_SIGNATURE;
+
+ /* remote block */
+ rtblock->remote_size = rtblock->size;
+ status = __ntapi->zw_allocate_virtual_memory(
+ hprocess,
+ &rtblock->remote_addr,
+ 0,
+ &rtblock->remote_size,
+ NT_MEM_RESERVE | NT_MEM_COMMIT,
+ NT_PAGE_READWRITE);
+
+ if (status != NT_STATUS_SUCCESS)
+ return status;
+
+ /* session handles */
+ if (rtblock->flags & NT_RUNTIME_DATA_DUPLICATE_SESSION_HANDLES) {
+ rtdata = (nt_runtime_data *)rtblock->addr;
+ srv_ready = rtdata->srv_ready;
+
+ status = __ntapi->zw_duplicate_object(
+ NT_CURRENT_PROCESS_HANDLE,
+ srv_ready,
+ hprocess,
+ &rtdata->srv_ready,
+ 0,0,NT_DUPLICATE_SAME_ATTRIBUTES | NT_DUPLICATE_SAME_ACCESS);
+ if (status) return status;
+ } else
+ srv_ready = 0;
+
+ /* copy local block to remote process */
+ status = __ntapi->zw_write_virtual_memory(
+ hprocess,
+ rtblock->remote_addr,
+ (char *)rtblock->addr,
+ rtblock->size,
+ &bytes_written);
+
+ /* restore rtdata */
+ if (srv_ready)
+ rtdata->srv_ready = srv_ready;
+
+ if (status != NT_STATUS_SUCCESS)
+ return status;
+
+ /* runtime_arg */
+ __ntapi->tt_uintptr_to_hex_utf16(
+ (uintptr_t)rtblock->remote_addr,
+ runtime_arg);
+
+ /* update remote runtime arg */
+ status = __ntapi->zw_write_virtual_memory(
+ hprocess,
+ pe_va_from_rva(
+ rcmd_line.buffer,
+ rcmd_line.strlen - sizeof(runtime_arg)),
+ (char *)&runtime_arg,
+ sizeof(runtime_arg),
+ &bytes_written);
+
+ if (status)
+ __ntapi->zw_free_virtual_memory(
+ hprocess,
+ &rtblock->remote_addr,
+ &rtblock->remote_size,
+ NT_MEM_RELEASE);
+
+ return status;
+}
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;
+}
diff --git a/src/process/ntapi_tt_fork_v2.c b/src/process/ntapi_tt_fork_v2.c
new file mode 100644
index 0000000..e483554
--- /dev/null
+++ b/src/process/ntapi_tt_fork_v2.c
@@ -0,0 +1,183 @@
+/********************************************************/
+/* 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_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_sync.h>
+#include <ntapi/nt_string.h>
+#include <ntapi/ntapi.h>
+#include "ntapi_impl.h"
+
+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_v2(
+ __out void ** hprocess,
+ __out void ** hthread)
+{
+ int32_t status;
+ void ** hport_session;
+ nt_object_attributes oa_process;
+ nt_object_attributes oa_thread;
+ nt_create_process_info process_info;
+ nt_cid cid;
+ nt_sec_img_inf sec_img_inf;
+ nt_timeout timeout;
+ ntapi_internals * __internals;
+
+ struct {
+ size_t size_in_bytes;
+ nt_create_process_ext_param process_info;
+ nt_create_process_ext_param section_info;
+ } ext_params;
+
+
+ oa_process.len = sizeof(nt_object_attributes);
+ oa_process.root_dir = 0;
+ oa_process.obj_name = 0;
+ oa_process.obj_attr = 0;
+ oa_process.sec_desc = 0;
+ oa_process.sec_qos = 0;
+
+ oa_thread.len = sizeof(nt_object_attributes);
+ oa_thread.root_dir = 0;
+ oa_thread.obj_name = 0;
+ oa_thread.obj_attr = 0;
+ oa_thread.sec_desc = 0;
+ oa_thread.sec_qos = 0;
+
+
+ __ntapi->tt_aligned_block_memset(
+ &process_info,0,sizeof(process_info));
+
+ process_info.size = sizeof(process_info);
+ process_info.state = NT_PROCESS_CREATE_INITIAL_STATE;
+ process_info.init_state.init_flags = NT_PROCESS_CREATE_FLAGS_NO_OBJECT_SYNC;
+
+ __ntapi->tt_aligned_block_memset(&ext_params,0,sizeof(ext_params));
+ __ntapi->tt_aligned_block_memset(&cid,0,sizeof(cid));
+ __ntapi->tt_aligned_block_memset(&sec_img_inf,0,sizeof(sec_img_inf));
+ ext_params.size_in_bytes = sizeof(ext_params);
+
+ ext_params.process_info.ext_param_type = NT_CREATE_PROCESS_EXT_PARAM_GET_CLIENT_ID;
+ ext_params.process_info.ext_param_size = sizeof(cid);
+ ext_params.process_info.ext_param_addr = &cid;
+
+ ext_params.section_info.ext_param_type = NT_CREATE_PROCESS_EXT_PARAM_GET_SECTION_IMAGE_INFO;
+ ext_params.section_info.ext_param_size = sizeof(sec_img_inf);
+ ext_params.section_info.ext_param_addr = &sec_img_inf;
+
+
+ /* [thou shalt remember the single step paradox] */
+ status = __ntapi->zw_create_user_process(
+ hprocess,
+ hthread,
+ NT_PROCESS_ALL_ACCESS,
+ NT_THREAD_ALL_ACCESS,
+ &oa_process,
+ &oa_thread,
+ NT_PROCESS_CREATE_FLAGS_INHERIT_HANDLES,
+ NT_PROCESS_CREATE_FLAGS_CREATE_THREAD_SUSPENDED,
+ (nt_process_parameters *)0,
+ &process_info,
+ (nt_create_process_ext_params *)&ext_params);
+
+ if (status == NT_STATUS_PROCESS_CLONED)
+ return 0;
+ else if (status)
+ return (intptr_t)(-1);
+
+ __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,
+ cid.process_id,
+ 0,0,&timeout)))
+ return __tt_fork_cancel(*hprocess,status);
+
+ /* [thou shalt remember the single step paradox] */
+ if ((status = __ntapi->zw_resume_thread(
+ *hthread,0)))
+ return __tt_fork_cancel(*hprocess,status);
+
+ /* hoppla */
+ return (int32_t)cid.process_id;
+}
+
+intptr_t __fastcall __ntapi_tt_fork_v2(
+ __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 (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_impl_v2(hprocess,hthread);
+
+ if (!hport_session || !*hport_session)
+ return pid;
+ else if (pid < 0)
+ return pid;
+
+ 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 {
+ 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;
+}
diff --git a/src/process/ntapi_tt_get_runtime_data.c b/src/process/ntapi_tt_get_runtime_data.c
new file mode 100644
index 0000000..92b4b2b
--- /dev/null
+++ b/src/process/ntapi_tt_get_runtime_data.c
@@ -0,0 +1,83 @@
+/********************************************************/
+/* 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_memory.h>
+#include <ntapi/nt_process.h>
+#include <ntapi/ntapi.h>
+#include "ntapi_impl.h"
+
+#if defined (__NT32)
+static wchar16_t runtime_arg[12] = {
+ ' ','-','r',' ',
+ 'i','n','t','e','g','r','a','l'};
+#elif defined (__NT64)
+static wchar16_t runtime_arg[20] = {
+ ' ','-','r',' ',
+ 'i','n','t','e','g','r','a','l',
+ '-','r','u','n','t','i','m','e'};
+#endif
+
+int32_t __stdcall __ntapi_tt_get_runtime_data(
+ __out nt_runtime_data ** rtdata,
+ __in wchar16_t ** argv)
+{
+ int32_t status;
+ nt_process_parameters * process_params;
+ nt_cmd_option_meta_utf16 cmd_opt_meta;
+ nt_runtime_data buffer;
+ nt_runtime_data * prtdata;
+ ntapi_internals * __internals;
+
+ /* init */
+ __internals = __ntapi_internals();
+
+ /* once? */
+ if (__internals->rtdata) {
+ *rtdata = __internals->rtdata;
+ return NT_STATUS_SUCCESS;
+ }
+
+ if (!(argv = argv ? argv : __internals->ntapi_img_sec_bss->argv_envp_array))
+ return NT_STATUS_INVALID_PARAMETER_2;
+
+ /* integral process? */
+ if ((status = __ntapi->tt_get_short_option_meta_utf16(
+ __ntapi->tt_crc32_table(),
+ 'r',
+ argv,
+ &cmd_opt_meta)))
+ return status;
+
+ else if (argv[3])
+ status = NT_STATUS_INVALID_PARAMETER_MIX;
+
+ if ((status = __ntapi->tt_hex_utf16_to_uintptr(
+ cmd_opt_meta.value,
+ (uintptr_t *)&prtdata)))
+ return status;
+
+ if ((status = __ntapi->zw_read_virtual_memory(
+ NT_CURRENT_PROCESS_HANDLE,
+ prtdata,
+ (char *)&buffer,
+ sizeof(buffer),0)))
+ return status;
+
+ /* avoid confusion :-) */
+ process_params = ((nt_peb *)pe_get_peb_address())->process_params;
+
+ __ntapi->tt_memcpy_utf16(
+ (wchar16_t *)pe_va_from_rva(
+ process_params->command_line.buffer,
+ process_params->command_line.strlen - sizeof(runtime_arg)),
+ runtime_arg,
+ sizeof(runtime_arg));
+
+ *rtdata = prtdata;
+
+ return NT_STATUS_SUCCESS;
+}
diff --git a/src/process/ntapi_tt_init_runtime_data.c b/src/process/ntapi_tt_init_runtime_data.c
new file mode 100644
index 0000000..c7c2603
--- /dev/null
+++ b/src/process/ntapi_tt_init_runtime_data.c
@@ -0,0 +1,82 @@
+/********************************************************/
+/* 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_memory.h>
+#include <ntapi/nt_process.h>
+#include <ntapi/ntapi.h>
+#include "ntapi_impl.h"
+
+int32_t __stdcall __ntapi_tt_update_runtime_data(nt_runtime_data * rtdata)
+{
+ int32_t status;
+ nt_process_basic_information pbi;
+ uint32_t ret;
+ nt_oa oa = {sizeof(oa)};
+
+ /* process (self) */
+ rtdata->cid_self.process_id = pe_get_current_process_id();
+ rtdata->cid_self.thread_id = 0;
+
+ if ((status = __ntapi->zw_open_process(
+ &rtdata->hprocess_self,
+ NT_PROCESS_ALL_ACCESS,
+ &oa,&rtdata->cid_self)))
+ return status;
+
+ if (rtdata->cid_parent.process_id)
+ return NT_STATUS_SUCCESS;
+
+ /* process (parent) */
+ if ((status = __ntapi->zw_query_information_process(
+ rtdata->hprocess_self,
+ NT_PROCESS_BASIC_INFORMATION,
+ &pbi,sizeof(pbi),&ret)))
+ return status;
+
+ rtdata->cid_parent.process_id = pbi.inherited_from_unique_process_id;
+ rtdata->cid_parent.thread_id = 0;
+ rtdata->hprocess_parent = 0;
+
+ return NT_STATUS_SUCCESS;
+}
+
+int32_t __stdcall __ntapi_tt_init_runtime_data(nt_runtime_data * rtdata)
+{
+ int32_t status;
+ nt_peb * peb;
+ nt_oa oa = {sizeof(oa)};
+
+ /* init */
+ __ntapi->tt_aligned_block_memset(rtdata,0,sizeof(*rtdata));
+ peb = (nt_peb *)(pe_get_peb_address());
+
+ /* pid (self,parent) */
+ if ((status = __ntapi_tt_update_runtime_data(rtdata)))
+ return status;
+
+ /* std handles */
+ rtdata->hstdin = peb->process_params->hstdin;
+ rtdata->hstdout = peb->process_params->hstdout;
+ rtdata->hstderr = peb->process_params->hstderr;
+
+ if (__ntapi->tt_get_file_handle_type(rtdata->hstdin,&rtdata->stdin_type)) {
+ rtdata->hstdin = NT_INVALID_HANDLE_VALUE;
+ rtdata->stdin_type = 0;
+ }
+
+ if (__ntapi->tt_get_file_handle_type(rtdata->hstdout,&rtdata->stdout_type)) {
+ rtdata->hstdout = NT_INVALID_HANDLE_VALUE;
+ rtdata->stdout_type = 0;
+ }
+
+ if (__ntapi->tt_get_file_handle_type(rtdata->hstderr,&rtdata->stderr_type)) {
+ rtdata->hstderr = NT_INVALID_HANDLE_VALUE;
+ rtdata->stderr_type = 0;
+ }
+
+ return 0;
+}
diff --git a/src/process/ntapi_tt_map_image_as_data.c b/src/process/ntapi_tt_map_image_as_data.c
new file mode 100644
index 0000000..864f9cc
--- /dev/null
+++ b/src/process/ntapi_tt_map_image_as_data.c
@@ -0,0 +1,120 @@
+/********************************************************/
+/* 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 <pemagine/pemagine.h>
+#include <ntapi/nt_section.h>
+#include <ntapi/nt_process.h>
+#include <ntapi/ntapi.h>
+#include "ntapi_impl.h"
+
+static nt_sqos const sqos = {
+ sizeof(sqos),
+ NT_SECURITY_IMPERSONATION,
+ NT_SECURITY_TRACKING_DYNAMIC,
+ 1};
+
+static int32_t __tt_exec_unmap_image(nt_executable_image * image, void * base, int32_t status)
+{
+ int32_t ret;
+
+ if (base)
+ if ((ret = __ntapi->zw_unmap_view_of_section(
+ NT_CURRENT_PROCESS_HANDLE,
+ base)))
+ return ret;
+
+ if (image->hsection)
+ if ((ret = __ntapi->zw_close(image->hsection)))
+ return ret;
+
+ return status;
+}
+
+int32_t __stdcall __ntapi_tt_exec_unmap_image(nt_executable_image * image)
+{
+ return __tt_exec_unmap_image(image,image->addr,0);
+}
+
+
+int32_t __stdcall __ntapi_tt_exec_map_image_as_data(nt_executable_image * image)
+{
+ int32_t status;
+ uint16_t * pi16;
+ uint32_t * pi32;
+ nt_sec_size sec_size;
+ size_t view_size;
+ void * base;
+ void * hsection;
+
+ struct pe_image_dos_hdr * dos;
+ struct pe_coff_file_hdr * coff;
+ union pe_opt_hdr * opt;
+ struct pe_sec_hdr * sec;
+
+ nt_oa oa = {sizeof(oa),
+ 0,0,0,0,(nt_sqos *)&sqos};
+
+ base = 0;
+ sec_size.quad = 0;
+ view_size = image->size;
+
+ if ((status = __ntapi->zw_create_section(
+ &hsection,
+ NT_SECTION_MAP_READ,
+ &oa,
+ &sec_size,
+ NT_PAGE_READONLY,
+ NT_SEC_RESERVE,image->hfile)))
+ return status;
+
+ if ((status = __ntapi->zw_map_view_of_section(
+ hsection,
+ NT_CURRENT_PROCESS_HANDLE,
+ &base,
+ 0,0,0,
+ &view_size,
+ NT_VIEW_UNMAP,0,
+ NT_PAGE_READONLY)))
+ return __tt_exec_unmap_image(
+ image,base,status);
+
+ if (!(dos = pe_get_image_dos_hdr_addr(base)))
+ return 0;
+
+ pi32 = (uint32_t *)dos->dos_lfanew;
+ if ((*pi32 + sizeof(*coff)) > view_size)
+ return __tt_exec_unmap_image(
+ image,base,NT_STATUS_INVALID_IMAGE_FORMAT);
+
+ if (!(coff = pe_get_image_coff_hdr_addr(base)))
+ return 0;
+
+ if (!(opt = pe_get_image_opt_hdr_addr(base)))
+ return 0;
+
+ sec = pe_get_image_section_tbl_addr(base);
+ pi16 = (uint16_t *)coff->num_of_sections;
+ if (((size_t)sec-(size_t)base + *pi16 * sizeof(*sec)) > view_size)
+ return __tt_exec_unmap_image(
+ image,base,NT_STATUS_INVALID_IMAGE_FORMAT);
+
+ /* subsystem: same offset (pe32, pe32+) */
+ pi16 = (uint16_t *)opt;
+ image->magic = *pi16;
+
+ pi16 = (uint16_t *)opt->opt_hdr_32.subsystem;
+ image->subsystem = *pi16;
+
+ pi16 = (uint16_t *)coff->characteristics;
+ image->characteristics = *pi16;
+
+ image->hsection = hsection;
+ image->addr = base;
+ image->size = view_size;
+
+ return status;
+}
diff --git a/src/process/tt_fork_v1.c b/src/process/tt_fork_v1.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/process/tt_fork_v1.c