diff options
author | midipix <writeonce@midipix.org> | 2015-07-27 04:01:18 -0400 |
---|---|---|
committer | midipix <writeonce@midipix.org> | 2015-07-27 04:01:18 -0400 |
commit | dd89bb8ad4fe184a34b5dbdda237e640fc82121b (patch) | |
tree | 5e80d2da35f5892f92be29f57982b2708e6bd99b /src/thread | |
parent | dcdadc2702712fa750ed255ed1dfa354522797a0 (diff) | |
download | ntapi-dd89bb8ad4fe184a34b5dbdda237e640fc82121b.tar.bz2 ntapi-dd89bb8ad4fe184a34b5dbdda237e640fc82121b.tar.xz |
entered advanced internal development stage.
Diffstat (limited to 'src/thread')
-rw-r--r-- | src/thread/ntapi_tt_create_thread.c | 418 |
1 files changed, 418 insertions, 0 deletions
diff --git a/src/thread/ntapi_tt_create_thread.c b/src/thread/ntapi_tt_create_thread.c new file mode 100644 index 0000000..4fbe68f --- /dev/null +++ b/src/thread/ntapi_tt_create_thread.c @@ -0,0 +1,418 @@ +/********************************************************/ +/* 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_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" + +/* (no planned support of alpha processors, use constant values) */ +#define __PAGE_SIZE 0x001000 +#define __GRANULARITY 0x010000 +#define __RESERVE_ROUND_UP 0x100000 + +static int32_t __stdcall __create_thread_fail( + void * hprocess, + void * stack_bottom, + size_t stack_size, + int32_t status) +{ + __ntapi->zw_free_virtual_memory( + hprocess, + &stack_bottom, + &stack_size, + NT_MEM_RELEASE); + return status; +} + +int32_t __stdcall __ntapi_tt_create_thread( + __in_out nt_thread_params * params) +{ + int32_t status; + ntapi_internals * __internals; + + nt_client_id cid; + nt_port_message_csrss_process csrss_msg; + nt_port_message_csrss_process * csrss_msg_1st; + nt_port_message_csrss_thread * csrss_msg_any; + + void * stack_system_limit; + uint32_t protect_type_old; + + nt_user_stack stack; + nt_thread_context context; + uintptr_t fsuspended; + uintptr_t * parg; + + if (!(params->stack_size_commit)) + return NT_STATUS_INVALID_PARAMETER; + else if (!(params->stack_size_reserve)) + return NT_STATUS_INVALID_PARAMETER; + else if (params->ext_ctx_size > __NT_INTERNAL_PAGE_SIZE) + return NT_STATUS_INVALID_PARAMETER; + else if (params->ext_ctx_size % sizeof(intptr_t)) + return NT_STATUS_INVALID_PARAMETER; + else if (params->arg && params->ext_ctx) + return NT_STATUS_INVALID_PARAMETER_MIX; + else if (params->ext_ctx && !params->ext_ctx_size) + return NT_STATUS_INVALID_PARAMETER_MIX; + + /* init */ + __internals = __ntapi_internals(); + params->stack_size_commit = __NT_ROUND_UP_TO_POWER_OF_2(params->stack_size_commit+params->ext_ctx_size, __PAGE_SIZE); + params->stack_size_reserve = __NT_ROUND_UP_TO_POWER_OF_2(params->stack_size_reserve,__GRANULARITY); + + /* compare, round-up as needed */ + if (params->stack_size_commit >= params->stack_size_reserve) + params->stack_size_reserve = __NT_ROUND_UP_TO_POWER_OF_2(params->stack_size_commit,__RESERVE_ROUND_UP); + + /** + * + * --------- BASE ---------- + * + * ---- (COMMITED AREA) ---- + * + * --------- LIMIT --------- + * + * ------ GUARD PAGE ------- + * + * ------ ACTUAL LIMIT ----- + * + * ---- (RESERVED AREA) ---- + * + * -------- BOTTOM --------- + * + **/ + + /* stack structure: unused fields */ + stack.fixed_stack_base = (void *)0; + stack.fixed_stack_limit = (void *)0; + + /* first we reserve */ + stack.expandable_stack_bottom = (void *)0; + status = __ntapi->zw_allocate_virtual_memory( + params->hprocess, + &stack.expandable_stack_bottom, + params->stack_zero_bits, + ¶ms->stack_size_reserve, + NT_MEM_RESERVE, + NT_PAGE_READWRITE); + + if (status) return status; + + /* calculate base and limit */ + stack.expandable_stack_base = + (void *)((intptr_t)stack.expandable_stack_bottom + + params->stack_size_reserve); + + stack.expandable_stack_limit = + (void *)((intptr_t)stack.expandable_stack_base + - params->stack_size_commit); + + /* guard page */ + params->stack_size_commit += __PAGE_SIZE; + stack_system_limit = + (void *)((intptr_t)stack.expandable_stack_base + - params->stack_size_commit); + + /* then we commit */ + status = __ntapi->zw_allocate_virtual_memory( + params->hprocess, + &stack_system_limit, + 0, + ¶ms->stack_size_commit, + NT_MEM_COMMIT, + NT_PAGE_READWRITE); + + if (status) return __create_thread_fail( + params->hprocess, + stack.expandable_stack_bottom, + params->stack_size_reserve, + status); + + /* finally we protect the guard page */ + params->stack_size_commit = __PAGE_SIZE; + status = __ntapi->zw_protect_virtual_memory( + params->hprocess, + &stack_system_limit, + ¶ms->stack_size_commit, + NT_PAGE_READWRITE | NT_MEM_PAGE_GUARD, + &protect_type_old); + + if (status) return __create_thread_fail( + params->hprocess, + stack.expandable_stack_bottom, + params->stack_size_reserve, + status); + + /* context */ + if (!params->reg_context) { + params->reg_context = &context; + __ntapi->tt_aligned_block_memset(&context,0,sizeof(nt_thread_context)); + __INIT_CONTEXT(context); + context.INSTRUCTION_POINTER_REGISTER = (uintptr_t)params->start; + context.STACK_POINTER_REGISTER = (uintptr_t)(stack.expandable_stack_base) + - sizeof(intptr_t); + } + + + + + + + +/*****************************************************************************/ +/*-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-*/ +/* */ +/* */ +/* INNOVATION IN THE FIELD OF MULTI-THREADED COMPUTER PROGRAMMING */ +/* */ +/* A "RAPUNZEL" TOP-OF-STACK, VARIABLE-SIZE ENTRY-ROUTINE CONTEXT */ +/* */ +/* COPYRIGHT (C) 2013,2014,2015 ZVI GILBOA */ +/* */ +/* */ +/* */ +/* Laß mir dein Haar herunter.« */ +/**/ if (params->ext_ctx) { /**/ +/**/ context.STACK_POINTER_REGISTER -= params->ext_ctx_size; /**/ +/**/ params->arg = (void *)context.STACK_POINTER_REGISTER; /**/ +/**/ /**/ +/**/ if (params->creation_flags & NT_CREATE_LOCAL_THREAD) /**/ +/**/ __ntapi->tt_aligned_block_memcpy( /**/ +/**/ (uintptr_t *)params->arg, /**/ +/**/ (uintptr_t *)params->ext_ctx, /**/ +/**/ params->ext_ctx_size); /**/ +/**/ else { /**/ +/**/ status = __ntapi->zw_write_virtual_memory( /**/ +/**/ params->hprocess, /**/ +/**/ params->arg, /**/ +/**/ (char *)params->ext_ctx, /**/ +/**/ params->ext_ctx_size, /**/ +/**/ 0); /**/ +/**/ /**/ +/**/ if (status) return __create_thread_fail( /**/ +/**/ params->hprocess, /**/ +/**/ stack.expandable_stack_bottom, /**/ +/**/ params->stack_size_reserve, /**/ +/**/ status); /**/ +/**/ } /**/ +/**/ } /**/ +/**/ /**/ +/**/ /**/ +/**/ /**/ +/* entry-routine argument address and stack pointer adjustment */ +/**/ if (sizeof(intptr_t) == 4) { /**/ +/**/ context.STACK_POINTER_REGISTER -= sizeof(intptr_t); /**/ +/**/ parg = (uintptr_t *)context.STACK_POINTER_REGISTER; /**/ +/**/ } else /**/ +/**/ parg = &context.FAST_CALL_ARG0; /**/ +/**/ /**/ +/**/ /**/ +/* write entry-routine argument */ +/**/ if ((sizeof(size_t) == 8) /**/ +/**/ || (params->creation_flags&NT_CREATE_LOCAL_THREAD))/**/ +/**/ *parg = (uintptr_t)params->arg; /**/ +/**/ else { /**/ +/**/ status = __ntapi->zw_write_virtual_memory( /**/ +/**/ params->hprocess, /**/ +/**/ parg, /**/ +/**/ (char *)¶ms->arg, /**/ +/**/ sizeof(uintptr_t), /**/ +/**/ 0); /**/ +/**/ /**/ +/**/ if (status) return __create_thread_fail( /**/ +/**/ params->hprocess, /**/ +/**/ stack.expandable_stack_bottom, /**/ +/**/ params->stack_size_reserve, /**/ +/**/ status); /**/ +/**/ } /**/ +/**/ /**/ +/**/ /**/ +/*-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-*/ +/*****************************************************************************/ + + + + + + + + + + + + /* create thread */ + if ((!__ntapi->zw_create_user_process) | (params->creation_flags & NT_CREATE_SUSPENDED)) + fsuspended = 1; + else + fsuspended = 0; + + status = __ntapi->zw_create_thread( + ¶ms->hthread, + NT_THREAD_ALL_ACCESS, + params->obj_attr, + params->hprocess, + &cid, + params->reg_context, + &stack, + fsuspended); + + if (status) return __create_thread_fail( + params->hprocess, + stack.expandable_stack_bottom, + params->stack_size_reserve, + status); + + /* for os versions prior to hasta la */ + if (!__ntapi->zw_create_user_process) { + __ntapi->tt_aligned_block_memset(&csrss_msg,0,sizeof(csrss_msg)); + + if (params->creation_flags & NT_CREATE_FIRST_THREAD_OF_PROCESS) { + /* nt_port_message_csrss_process is the larger structure */ + csrss_msg_1st = &csrss_msg; + + csrss_msg_1st->header.data_size = sizeof(nt_port_message_csrss_process) - sizeof(nt_port_message); + csrss_msg_1st->header.msg_size = sizeof(nt_port_message_csrss_process); + csrss_msg_1st->opcode = 0x10000; + csrss_msg_1st->hprocess = params->hprocess; + csrss_msg_1st->hthread = params->hthread; + csrss_msg_1st->unique_process_id = cid.process_id; + csrss_msg_1st->unique_thread_id = cid.thread_id; + } else { + /* nt_port_message_csrss_thread is the smaller structure */ + csrss_msg_any = (nt_port_message_csrss_thread *)&csrss_msg; + + csrss_msg_any->header.data_size = sizeof(nt_port_message_csrss_thread) - sizeof(nt_port_message); + csrss_msg_any->header.msg_size = sizeof(nt_port_message_csrss_thread); + csrss_msg_any->opcode = 0x10001; + csrss_msg_any->hthread = params->hthread; + csrss_msg_any->unique_process_id = cid.process_id; + csrss_msg_any->unique_thread_id = cid.thread_id; + } + + /* send csrss a new-thread notification */ + if (__internals->csr_port_handle_addr) { + status = __ntapi->zw_request_wait_reply_port( + *__internals->csr_port_handle_addr, + &csrss_msg,&csrss_msg); + } + + /* output csrss_status to caller */ + params->csrss_status = status + ? status + : csrss_msg.status; + } + + /* resume thread, close handle as needed */ + if (fsuspended && !(params->creation_flags & NT_CREATE_SUSPENDED)) + status = __ntapi->zw_resume_thread(params->hthread,0); + + if (params->creation_flags & NT_CLOSE_THREAD_HANDLE) + __ntapi->zw_close(params->hthread); + + /* and finally */ + params->thread_id = (uint32_t)cid.thread_id; + return NT_STATUS_SUCCESS; +} + + +int32_t __stdcall __ntapi_tt_create_local_thread( + __in_out nt_thread_params * params) +{ + void * image_base; + struct pe_stack_heap_info stack_heap_info; + nt_client_id cid; + nt_object_attributes oa; + nt_status status; + + /* oa init */ + oa.len = sizeof(oa); + oa.root_dir = (void *)0; + oa.obj_name = (nt_unicode_string *)0; + oa.obj_attr = 0; + oa.sec_desc = (nt_sd *)0; + oa.sec_qos = (nt_sqos *)0; + + /* init cid */ + cid.process_id = pe_get_current_process_id(); + cid.thread_id = pe_get_current_thread_id(); + + /* obtain a handle to our own process */ + /* TODO: use cached handle, no close */ + status = __ntapi->zw_open_process( + ¶ms->hprocess, + NT_PROCESS_ALL_ACCESS, + &oa, + &cid); + + if (status) return status; + + /* retrieve the stack defaults as needed */ + if (!(params->stack_size_commit && params->stack_size_reserve) && !(params->stack_info)) { + /* image_base*/ + image_base = pe_get_first_module_handle(); + + if (!(intptr_t)image_base) + return NT_STATUS_INVALID_IMPORT_OF_NON_DLL; + + status = pe_get_image_stack_heap_info( + image_base, + &stack_heap_info); + + if (status) + return NT_STATUS_INVALID_IMAGE_FORMAT; + + /* stack_size_commit */ + if (!params->stack_size_commit) + params->stack_size_commit = stack_heap_info.size_of_stack_commit; + + /* stack_size_reserve */ + if (!params->stack_size_reserve) + params->stack_size_reserve = stack_heap_info.size_of_stack_reserve; + + if (!(params->stack_size_commit && params->stack_size_reserve)) + return NT_STATUS_INVALID_IMAGE_FORMAT; + } + + params->creation_flags |= NT_CREATE_LOCAL_THREAD; + status = __ntapi_tt_create_thread(params); + + /* TODO: use cached handle, no close */ + __ntapi->zw_close(params->hprocess); + return status; +} + + +int32_t __stdcall __ntapi_tt_create_remote_thread( + __in_out nt_thread_params * params) +{ + return __ntapi_tt_create_thread(params); +} + + +void * __cdecl __ntapi_csr_port_handle(nt_status * pstatus) +{ + ntapi_internals * __internals; + + __internals = __ntapi_internals(); + + if (__internals->csr_port_handle_addr) { + if (pstatus) + *pstatus = NT_STATUS_SUCCESS; + return *__internals->csr_port_handle_addr; + } else { + if (pstatus) + *pstatus = NT_STATUS_UNSUCCESSFUL; + return (void *)0; + } +} |