| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| static int32_t __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; |
| } |
| |
| |
| static int32_t __tt_create_thread_stack( |
| nt_thread_params * params, |
| nt_user_stack * stack) |
| { |
| int32_t status; |
| uint32_t protect_type_old; |
| void * stack_system_limit; |
| char * base; |
| size_t size; |
| size_t commit; |
| |
| |
| if (params->stack_info && params->stack_info->expandable_stack_base) { |
| stack->fixed_stack_base = params->stack_info->fixed_stack_base; |
| stack->fixed_stack_limit = params->stack_info->fixed_stack_limit; |
| stack->expandable_stack_base = params->stack_info->expandable_stack_base; |
| stack->expandable_stack_limit = params->stack_info->expandable_stack_limit; |
| stack->expandable_stack_bottom = params->stack_info->expandable_stack_bottom; |
| |
| return NT_STATUS_SUCCESS; |
| } |
| |
| |
| 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); |
| |
| |
| 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); |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| stack->fixed_stack_base = 0; |
| stack->fixed_stack_limit = 0; |
| |
| |
| stack->expandable_stack_bottom = 0; |
| |
| if ((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))) |
| return status; |
| |
| |
| base = stack->expandable_stack_bottom; |
| base += params->stack_size_reserve; |
| |
| stack->expandable_stack_base = base; |
| stack->expandable_stack_limit = base - params->stack_size_commit; |
| |
| |
| commit = params->stack_size_commit + __PAGE_SIZE; |
| stack_system_limit = base - commit; |
| |
| |
| if ((status = __ntapi->zw_allocate_virtual_memory( |
| params->hprocess, |
| &stack_system_limit, |
| 0,&commit, |
| NT_MEM_COMMIT, |
| NT_PAGE_READWRITE))) |
| return __create_thread_fail( |
| params->hprocess, |
| stack->expandable_stack_bottom, |
| params->stack_size_reserve, |
| status); |
| |
| |
| size = __PAGE_SIZE; |
| |
| if ((status = __ntapi->zw_protect_virtual_memory( |
| params->hprocess, |
| &stack_system_limit, |
| &size, |
| NT_PAGE_READWRITE | NT_MEM_PAGE_GUARD, |
| &protect_type_old))) |
| return __create_thread_fail( |
| params->hprocess, |
| stack->expandable_stack_bottom, |
| params->stack_size_reserve, |
| status); |
| |
| |
| if (params->stack_info) { |
| params->stack_info->fixed_stack_base = stack->fixed_stack_base; |
| params->stack_info->fixed_stack_limit = stack->fixed_stack_limit; |
| params->stack_info->expandable_stack_base = stack->expandable_stack_base; |
| params->stack_info->expandable_stack_limit = stack->expandable_stack_limit; |
| params->stack_info->expandable_stack_bottom = stack->expandable_stack_bottom; |
| |
| return NT_STATUS_SUCCESS; |
| } |
| |
| return NT_STATUS_SUCCESS; |
| } |
| |
| int32_t __stdcall __ntapi_tt_create_thread(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; |
| |
| nt_thread_context __attr_aligned__(0x40) context; |
| nt_user_stack __attr_aligned__(0x10) stack; |
| 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; |
| |
| |
| __internals = __ntapi_internals(); |
| |
| |
| if ((status = __tt_create_thread_stack(params,&stack))) |
| return status; |
| |
| |
| if (params->reg_context) { |
| __ntapi->tt_aligned_block_memcpy( |
| (uintptr_t *)&context, |
| (uintptr_t *)params->reg_context, |
| sizeof(context)); |
| } else { |
| __ntapi->tt_aligned_block_memset( |
| &context,0,sizeof(context)); |
| |
| __INIT_CONTEXT(context); |
| context.INSTRUCTION_POINTER_REGISTER = (uintptr_t)params->start; |
| context.STACK_POINTER_REGISTER = (uintptr_t)(stack.expandable_stack_base); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| 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); |
| |
| __ntapi->tt_aligned_block_memlock( |
| (uintptr_t *)params->arg, |
| 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); |
| } |
| } |
| |
| |
| |
| |
| 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; |
| } |
| |
| |
| |
| if (sizeof(intptr_t) == 8) { |
| at_store( |
| (intptr_t *)parg, |
| (intptr_t)params->arg); |
| |
| } else if (params->creation_flags & NT_CREATE_LOCAL_THREAD) { |
| at_store( |
| (intptr_t *)parg, |
| (intptr_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); |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| fsuspended = (params->creation_flags & NT_CREATE_SUSPENDED) |
| ? 1 : __ntapi->zw_create_user_process |
| ? 0 : 1; |
| |
| if ((status = __ntapi->zw_create_thread( |
| ¶ms->hthread, |
| NT_THREAD_ALL_ACCESS, |
| params->obj_attr, |
| params->hprocess, |
| &cid,&context,&stack, |
| fsuspended))) |
| return __create_thread_fail( |
| params->hprocess, |
| stack.expandable_stack_bottom, |
| params->stack_size_reserve, |
| status); |
| |
| |
| 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) { |
| |
| 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 { |
| |
| 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; |
| } |
| |
| |
| if (__internals->csr_port_handle_addr) { |
| status = __ntapi->zw_request_wait_reply_port( |
| *__internals->csr_port_handle_addr, |
| &csrss_msg,&csrss_msg); |
| } |
| |
| |
| params->csrss_status = status |
| ? status |
| : csrss_msg.status; |
| } |
| |
| |
| 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); |
| |
| |
| params->cid.process_id = cid.process_id; |
| params->cid.thread_id = cid.thread_id; |
| |
| return NT_STATUS_SUCCESS; |
| } |
| |
| |
| int32_t __stdcall __ntapi_tt_create_local_thread(nt_thread_params * params) |
| { |
| nt_status status; |
| void * image_base; |
| struct pe_stack_heap_info stack_heap_info; |
| |
| |
| params->creation_flags |= NT_CREATE_LOCAL_THREAD; |
| |
| |
| if (!params->hprocess) |
| params->hprocess = __ntapi_internals()->hprocess; |
| |
| |
| if (params->stack_info) |
| (void)0; |
| |
| else if (params->stack_size_commit && params->stack_size_reserve) |
| (void)0; |
| |
| else { |
| |
| if (!(image_base = pe_get_first_module_handle())) |
| return NT_STATUS_INVALID_IMPORT_OF_NON_DLL; |
| |
| if ((status = pe_get_image_stack_heap_info( |
| image_base, |
| &stack_heap_info))) |
| return NT_STATUS_INVALID_IMAGE_FORMAT; |
| |
| |
| if (!params->stack_size_commit) |
| params->stack_size_commit = stack_heap_info.size_of_stack_commit; |
| |
| |
| 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; |
| } |
| |
| return __ntapi_tt_create_thread(params); |
| } |
| |
| |
| int32_t __stdcall __ntapi_tt_create_remote_thread(nt_thread_params * params) |
| { |
| return __ntapi_tt_create_thread(params); |
| } |
| |
| |
| void * __cdecl __ntapi_csr_port_handle(nt_status * pstatus) |
| { |
| nt_status status; |
| ntapi_internals * __internals; |
| |
| pstatus = pstatus ? pstatus : &status; |
| __internals = __ntapi_internals(); |
| |
| if (__internals->csr_port_handle_addr) { |
| *pstatus = NT_STATUS_SUCCESS; |
| return *__internals->csr_port_handle_addr; |
| } else { |
| *pstatus = NT_STATUS_UNSUCCESSFUL; |
| return 0; |
| } |
| } |