|
|
dd89bb |
/********************************************************/
|
|
|
dd89bb |
|
|
|
4256e2 |
|
|
|
dd89bb |
|
|
|
dd89bb |
/********************************************************/
|
|
|
dd89bb |
|
|
|
dd89bb |
#include <psxtypes/psxtypes.h>
|
|
|
dd89bb |
#include <pemagine/pemagine.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 |
/* (no planned support of alpha processors, use constant values) */
|
|
|
dd89bb |
#define __PAGE_SIZE 0x001000
|
|
|
dd89bb |
#define __GRANULARITY 0x010000
|
|
|
dd89bb |
#define __RESERVE_ROUND_UP 0x100000
|
|
|
dd89bb |
|
|
|
dd89bb |
static int32_t __stdcall __create_thread_fail(
|
|
|
dd89bb |
void * hprocess,
|
|
|
dd89bb |
void * stack_bottom,
|
|
|
dd89bb |
size_t stack_size,
|
|
|
dd89bb |
int32_t status)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
__ntapi->zw_free_virtual_memory(
|
|
|
dd89bb |
hprocess,
|
|
|
dd89bb |
&stack_bottom,
|
|
|
dd89bb |
&stack_size,
|
|
|
dd89bb |
NT_MEM_RELEASE);
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
int32_t __stdcall __ntapi_tt_create_thread(
|
|
|
dd89bb |
__in_out nt_thread_params * params)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
int32_t status;
|
|
|
dd89bb |
ntapi_internals * __internals;
|
|
|
dd89bb |
|
|
|
dd89bb |
nt_client_id cid;
|
|
|
dd89bb |
nt_port_message_csrss_process csrss_msg;
|
|
|
dd89bb |
nt_port_message_csrss_process * csrss_msg_1st;
|
|
|
dd89bb |
nt_port_message_csrss_thread * csrss_msg_any;
|
|
|
dd89bb |
|
|
|
dd89bb |
void * stack_system_limit;
|
|
|
dd89bb |
uint32_t protect_type_old;
|
|
|
dd89bb |
|
|
|
9f88a2 |
nt_thread_context context __attr_aligned__(0x40);
|
|
|
9f88a2 |
nt_user_stack stack __attr_aligned__(0x10);
|
|
|
dd89bb |
uintptr_t fsuspended;
|
|
|
dd89bb |
uintptr_t * parg;
|
|
|
dd89bb |
|
|
|
dd89bb |
if (!(params->stack_size_commit))
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER;
|
|
|
dd89bb |
else if (!(params->stack_size_reserve))
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER;
|
|
|
dd89bb |
else if (params->ext_ctx_size > __NT_INTERNAL_PAGE_SIZE)
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER;
|
|
|
dd89bb |
else if (params->ext_ctx_size % sizeof(intptr_t))
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER;
|
|
|
dd89bb |
else if (params->arg && params->ext_ctx)
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER_MIX;
|
|
|
dd89bb |
else if (params->ext_ctx && !params->ext_ctx_size)
|
|
|
dd89bb |
return NT_STATUS_INVALID_PARAMETER_MIX;
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
__internals = __ntapi_internals();
|
|
|
dd89bb |
params->stack_size_commit = __NT_ROUND_UP_TO_POWER_OF_2(params->stack_size_commit+params->ext_ctx_size, __PAGE_SIZE);
|
|
|
dd89bb |
params->stack_size_reserve = __NT_ROUND_UP_TO_POWER_OF_2(params->stack_size_reserve,__GRANULARITY);
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
if (params->stack_size_commit >= params->stack_size_reserve)
|
|
|
dd89bb |
params->stack_size_reserve = __NT_ROUND_UP_TO_POWER_OF_2(params->stack_size_commit,__RESERVE_ROUND_UP);
|
|
|
dd89bb |
|
|
|
dd89bb |
/**
|
|
|
dd89bb |
*
|
|
|
dd89bb |
*
|
|
|
dd89bb |
*
|
|
|
dd89bb |
*
|
|
|
dd89bb |
*
|
|
|
dd89bb |
*
|
|
|
dd89bb |
*
|
|
|
dd89bb |
*
|
|
|
dd89bb |
*
|
|
|
dd89bb |
*
|
|
|
dd89bb |
*
|
|
|
dd89bb |
*
|
|
|
dd89bb |
*
|
|
|
dd89bb |
*
|
|
|
dd89bb |
*
|
|
|
dd89bb |
**/
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
stack.fixed_stack_base = (void *)0;
|
|
|
dd89bb |
stack.fixed_stack_limit = (void *)0;
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
stack.expandable_stack_bottom = (void *)0;
|
|
|
dd89bb |
status = __ntapi->zw_allocate_virtual_memory(
|
|
|
dd89bb |
params->hprocess,
|
|
|
dd89bb |
&stack.expandable_stack_bottom,
|
|
|
dd89bb |
params->stack_zero_bits,
|
|
|
dd89bb |
¶ms->stack_size_reserve,
|
|
|
dd89bb |
NT_MEM_RESERVE,
|
|
|
dd89bb |
NT_PAGE_READWRITE);
|
|
|
dd89bb |
|
|
|
dd89bb |
if (status) return status;
|
|
|
dd89bb |
|
|
|
dd89bb |
/* calculate base and limit */
|
|
|
dd89bb |
stack.expandable_stack_base =
|
|
|
dd89bb |
(void *)((intptr_t)stack.expandable_stack_bottom
|
|
|
dd89bb |
+ params->stack_size_reserve);
|
|
|
dd89bb |
|
|
|
dd89bb |
stack.expandable_stack_limit =
|
|
|
dd89bb |
(void *)((intptr_t)stack.expandable_stack_base
|
|
|
dd89bb |
- params->stack_size_commit);
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
params->stack_size_commit += __PAGE_SIZE;
|
|
|
dd89bb |
stack_system_limit =
|
|
|
dd89bb |
(void *)((intptr_t)stack.expandable_stack_base
|
|
|
dd89bb |
- params->stack_size_commit);
|
|
|
dd89bb |
|
|
|
dd89bb |
/* then we commit */
|
|
|
dd89bb |
status = __ntapi->zw_allocate_virtual_memory(
|
|
|
dd89bb |
params->hprocess,
|
|
|
dd89bb |
&stack_system_limit,
|
|
|
dd89bb |
0,
|
|
|
dd89bb |
¶ms->stack_size_commit,
|
|
|
dd89bb |
NT_MEM_COMMIT,
|
|
|
dd89bb |
NT_PAGE_READWRITE);
|
|
|
dd89bb |
|
|
|
dd89bb |
if (status) return __create_thread_fail(
|
|
|
dd89bb |
params->hprocess,
|
|
|
dd89bb |
stack.expandable_stack_bottom,
|
|
|
dd89bb |
params->stack_size_reserve,
|
|
|
dd89bb |
status);
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
params->stack_size_commit = __PAGE_SIZE;
|
|
|
dd89bb |
status = __ntapi->zw_protect_virtual_memory(
|
|
|
dd89bb |
params->hprocess,
|
|
|
dd89bb |
&stack_system_limit,
|
|
|
dd89bb |
¶ms->stack_size_commit,
|
|
|
dd89bb |
NT_PAGE_READWRITE | NT_MEM_PAGE_GUARD,
|
|
|
dd89bb |
&protect_type_old);
|
|
|
dd89bb |
|
|
|
dd89bb |
if (status) return __create_thread_fail(
|
|
|
dd89bb |
params->hprocess,
|
|
|
dd89bb |
stack.expandable_stack_bottom,
|
|
|
dd89bb |
params->stack_size_reserve,
|
|
|
dd89bb |
status);
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
if (!params->reg_context) {
|
|
|
dd89bb |
params->reg_context = &context;
|
|
|
dd89bb |
__ntapi->tt_aligned_block_memset(&context,0,sizeof(nt_thread_context));
|
|
|
dd89bb |
__INIT_CONTEXT(context);
|
|
|
dd89bb |
context.INSTRUCTION_POINTER_REGISTER = (uintptr_t)params->start;
|
|
|
dd89bb |
context.STACK_POINTER_REGISTER = (uintptr_t)(stack.expandable_stack_base)
|
|
|
dd89bb |
- sizeof(intptr_t);
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
/*****************************************************************************/
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
/* A "RAPUNZEL" TOP-OF-STACK, VARIABLE-SIZE ENTRY-ROUTINE CONTEXT */
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
if (params->ext_ctx) {
|
|
|
dd89bb |
context.STACK_POINTER_REGISTER -= params->ext_ctx_size;
|
|
|
dd89bb |
params->arg = (void *)context.STACK_POINTER_REGISTER;
|
|
|
dd89bb |
|
|
|
dd89bb |
if (params->creation_flags & NT_CREATE_LOCAL_THREAD)
|
|
|
dd89bb |
__ntapi->tt_aligned_block_memcpy(
|
|
|
dd89bb |
(uintptr_t *)params->arg,
|
|
|
dd89bb |
(uintptr_t *)params->ext_ctx,
|
|
|
dd89bb |
params->ext_ctx_size);
|
|
|
dd89bb |
else {
|
|
|
dd89bb |
status = __ntapi->zw_write_virtual_memory(
|
|
|
dd89bb |
params->hprocess,
|
|
|
dd89bb |
params->arg,
|
|
|
dd89bb |
(char *)params->ext_ctx,
|
|
|
dd89bb |
params->ext_ctx_size,
|
|
|
dd89bb |
0);
|
|
|
dd89bb |
|
|
|
dd89bb |
if (status) return __create_thread_fail(
|
|
|
dd89bb |
params->hprocess,
|
|
|
dd89bb |
stack.expandable_stack_bottom,
|
|
|
dd89bb |
params->stack_size_reserve,
|
|
|
dd89bb |
status);
|
|
|
dd89bb |
}
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
if (sizeof(intptr_t) == 4) {
|
|
|
dd89bb |
context.STACK_POINTER_REGISTER -= sizeof(intptr_t);
|
|
|
dd89bb |
parg = (uintptr_t *)context.STACK_POINTER_REGISTER;
|
|
|
dd89bb |
} else
|
|
|
dd89bb |
parg = &context.FAST_CALL_ARG0;
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
if ((sizeof(size_t) == 8)
|
|
|
dd89bb |
|| (params->creation_flags&NT_CREATE_LOCAL_THREAD))
|
|
|
dd89bb |
*parg = (uintptr_t)params->arg;
|
|
|
dd89bb |
else {
|
|
|
dd89bb |
status = __ntapi->zw_write_virtual_memory(
|
|
|
dd89bb |
params->hprocess,
|
|
|
dd89bb |
parg,
|
|
|
dd89bb |
(char *)¶ms->arg,
|
|
|
dd89bb |
sizeof(uintptr_t),
|
|
|
dd89bb |
0);
|
|
|
dd89bb |
|
|
|
dd89bb |
if (status) return __create_thread_fail(
|
|
|
dd89bb |
params->hprocess,
|
|
|
dd89bb |
stack.expandable_stack_bottom,
|
|
|
dd89bb |
params->stack_size_reserve,
|
|
|
dd89bb |
status);
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
/*****************************************************************************/
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
if ((!__ntapi->zw_create_user_process) | (params->creation_flags & NT_CREATE_SUSPENDED))
|
|
|
dd89bb |
fsuspended = 1;
|
|
|
dd89bb |
else
|
|
|
dd89bb |
fsuspended = 0;
|
|
|
dd89bb |
|
|
|
dd89bb |
status = __ntapi->zw_create_thread(
|
|
|
dd89bb |
¶ms->hthread,
|
|
|
dd89bb |
NT_THREAD_ALL_ACCESS,
|
|
|
dd89bb |
params->obj_attr,
|
|
|
dd89bb |
params->hprocess,
|
|
|
dd89bb |
&cid,
|
|
|
dd89bb |
params->reg_context,
|
|
|
dd89bb |
&stack,
|
|
|
dd89bb |
fsuspended);
|
|
|
dd89bb |
|
|
|
dd89bb |
if (status) return __create_thread_fail(
|
|
|
dd89bb |
params->hprocess,
|
|
|
dd89bb |
stack.expandable_stack_bottom,
|
|
|
dd89bb |
params->stack_size_reserve,
|
|
|
dd89bb |
status);
|
|
|
dd89bb |
|
|
|
dd89bb |
/* for os versions prior to hasta la */
|
|
|
dd89bb |
if (!__ntapi->zw_create_user_process) {
|
|
|
dd89bb |
__ntapi->tt_aligned_block_memset(&csrss_msg,0,sizeof(csrss_msg));
|
|
|
dd89bb |
|
|
|
dd89bb |
if (params->creation_flags & NT_CREATE_FIRST_THREAD_OF_PROCESS) {
|
|
|
dd89bb |
|
|
|
dd89bb |
csrss_msg_1st = &csrss_msg;
|
|
|
dd89bb |
|
|
|
dd89bb |
csrss_msg_1st->header.data_size = sizeof(nt_port_message_csrss_process) - sizeof(nt_port_message);
|
|
|
dd89bb |
csrss_msg_1st->header.msg_size = sizeof(nt_port_message_csrss_process);
|
|
|
dd89bb |
csrss_msg_1st->opcode = 0x10000;
|
|
|
dd89bb |
csrss_msg_1st->hprocess = params->hprocess;
|
|
|
dd89bb |
csrss_msg_1st->hthread = params->hthread;
|
|
|
dd89bb |
csrss_msg_1st->unique_process_id = cid.process_id;
|
|
|
dd89bb |
csrss_msg_1st->unique_thread_id = cid.thread_id;
|
|
|
dd89bb |
} else {
|
|
|
dd89bb |
|
|
|
dd89bb |
csrss_msg_any = (nt_port_message_csrss_thread *)&csrss_msg;
|
|
|
dd89bb |
|
|
|
dd89bb |
csrss_msg_any->header.data_size = sizeof(nt_port_message_csrss_thread) - sizeof(nt_port_message);
|
|
|
dd89bb |
csrss_msg_any->header.msg_size = sizeof(nt_port_message_csrss_thread);
|
|
|
dd89bb |
csrss_msg_any->opcode = 0x10001;
|
|
|
dd89bb |
csrss_msg_any->hthread = params->hthread;
|
|
|
dd89bb |
csrss_msg_any->unique_process_id = cid.process_id;
|
|
|
dd89bb |
csrss_msg_any->unique_thread_id = cid.thread_id;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
if (__internals->csr_port_handle_addr) {
|
|
|
dd89bb |
status = __ntapi->zw_request_wait_reply_port(
|
|
|
dd89bb |
*__internals->csr_port_handle_addr,
|
|
|
dd89bb |
&csrss_msg,&csrss_msg);
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
/* output csrss_status to caller */
|
|
|
dd89bb |
params->csrss_status = status
|
|
|
dd89bb |
? status
|
|
|
dd89bb |
: csrss_msg.status;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
/* resume thread, close handle as needed */
|
|
|
dd89bb |
if (fsuspended && !(params->creation_flags & NT_CREATE_SUSPENDED))
|
|
|
dd89bb |
status = __ntapi->zw_resume_thread(params->hthread,0);
|
|
|
dd89bb |
|
|
|
dd89bb |
if (params->creation_flags & NT_CLOSE_THREAD_HANDLE)
|
|
|
dd89bb |
__ntapi->zw_close(params->hthread);
|
|
|
dd89bb |
|
|
|
dd89bb |
/* and finally */
|
|
|
dd89bb |
params->thread_id = (uint32_t)cid.thread_id;
|
|
|
dd89bb |
return NT_STATUS_SUCCESS;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
int32_t __stdcall __ntapi_tt_create_local_thread(
|
|
|
dd89bb |
__in_out nt_thread_params * params)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
void * image_base;
|
|
|
dd89bb |
struct pe_stack_heap_info stack_heap_info;
|
|
|
dd89bb |
nt_client_id cid;
|
|
|
dd89bb |
nt_object_attributes oa;
|
|
|
dd89bb |
nt_status status;
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
oa.len = sizeof(oa);
|
|
|
dd89bb |
oa.root_dir = (void *)0;
|
|
|
dd89bb |
oa.obj_name = (nt_unicode_string *)0;
|
|
|
dd89bb |
oa.obj_attr = 0;
|
|
|
dd89bb |
oa.sec_desc = (nt_sd *)0;
|
|
|
dd89bb |
oa.sec_qos = (nt_sqos *)0;
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
cid.process_id = pe_get_current_process_id();
|
|
|
dd89bb |
cid.thread_id = pe_get_current_thread_id();
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
/* TODO: use cached handle, no close */
|
|
|
dd89bb |
status = __ntapi->zw_open_process(
|
|
|
dd89bb |
¶ms->hprocess,
|
|
|
dd89bb |
NT_PROCESS_ALL_ACCESS,
|
|
|
dd89bb |
&oa,
|
|
|
dd89bb |
&cid;;
|
|
|
dd89bb |
|
|
|
dd89bb |
if (status) return status;
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
if (!(params->stack_size_commit && params->stack_size_reserve) && !(params->stack_info)) {
|
|
|
dd89bb |
|
|
|
dd89bb |
image_base = pe_get_first_module_handle();
|
|
|
dd89bb |
|
|
|
dd89bb |
if (!(intptr_t)image_base)
|
|
|
dd89bb |
return NT_STATUS_INVALID_IMPORT_OF_NON_DLL;
|
|
|
dd89bb |
|
|
|
dd89bb |
status = pe_get_image_stack_heap_info(
|
|
|
dd89bb |
image_base,
|
|
|
dd89bb |
&stack_heap_info);
|
|
|
dd89bb |
|
|
|
dd89bb |
if (status)
|
|
|
dd89bb |
return NT_STATUS_INVALID_IMAGE_FORMAT;
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
if (!params->stack_size_commit)
|
|
|
dd89bb |
params->stack_size_commit = stack_heap_info.size_of_stack_commit;
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
if (!params->stack_size_reserve)
|
|
|
dd89bb |
params->stack_size_reserve = stack_heap_info.size_of_stack_reserve;
|
|
|
dd89bb |
|
|
|
dd89bb |
if (!(params->stack_size_commit && params->stack_size_reserve))
|
|
|
dd89bb |
return NT_STATUS_INVALID_IMAGE_FORMAT;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
params->creation_flags |= NT_CREATE_LOCAL_THREAD;
|
|
|
dd89bb |
status = __ntapi_tt_create_thread(params);
|
|
|
dd89bb |
|
|
|
dd89bb |
/* TODO: use cached handle, no close */
|
|
|
dd89bb |
__ntapi->zw_close(params->hprocess);
|
|
|
dd89bb |
return status;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
int32_t __stdcall __ntapi_tt_create_remote_thread(
|
|
|
dd89bb |
__in_out nt_thread_params * params)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
return __ntapi_tt_create_thread(params);
|
|
|
dd89bb |
}
|
|
|
dd89bb |
|
|
|
dd89bb |
|
|
|
dd89bb |
void * __cdecl __ntapi_csr_port_handle(nt_status * pstatus)
|
|
|
dd89bb |
{
|
|
|
dd89bb |
ntapi_internals * __internals;
|
|
|
dd89bb |
|
|
|
dd89bb |
__internals = __ntapi_internals();
|
|
|
dd89bb |
|
|
|
dd89bb |
if (__internals->csr_port_handle_addr) {
|
|
|
dd89bb |
if (pstatus)
|
|
|
dd89bb |
*pstatus = NT_STATUS_SUCCESS;
|
|
|
dd89bb |
return *__internals->csr_port_handle_addr;
|
|
|
dd89bb |
} else {
|
|
|
dd89bb |
if (pstatus)
|
|
|
dd89bb |
*pstatus = NT_STATUS_UNSUCCESSFUL;
|
|
|
dd89bb |
return (void *)0;
|
|
|
dd89bb |
}
|
|
|
dd89bb |
}
|