From 2db6fe4f1847b6461991756e3cc5bc7b31d41282 Mon Sep 17 00:00:00 2001
From: midipix <writeonce@midipix.org>
Date: Fri, 19 Jan 2018 22:49:45 +0000
Subject: __ntapi_tt_create_thread(): support caller-provided thread stack.

---
 src/thread/ntapi_tt_create_thread.c | 124 +++++++++++++++++++++++-------------
 1 file changed, 81 insertions(+), 43 deletions(-)

(limited to 'src/thread')

diff --git a/src/thread/ntapi_tt_create_thread.c b/src/thread/ntapi_tt_create_thread.c
index a8dcb11..c356370 100644
--- a/src/thread/ntapi_tt_create_thread.c
+++ b/src/thread/ntapi_tt_create_thread.c
@@ -34,42 +34,30 @@ static int32_t __create_thread_fail(
 	return status;
 }
 
-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;
 
-	char *			base;
-	void *			stack_system_limit;
-	uint32_t		protect_type_old;
-
-	nt_thread_context 	__attr_aligned__(0x40) context;
-	nt_user_stack		__attr_aligned__(0x10) stack;
-	uintptr_t		fsuspended;
-	uintptr_t *		parg;
-	size_t			size;
-	size_t			commit;
-
-	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;
+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;
+
+	/* caller-provided stack? */
+	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;
+	}
 
 	/* 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);
 
@@ -96,15 +84,15 @@ int32_t __stdcall __ntapi_tt_create_thread(nt_thread_params * params)
 	**/
 
 	/* stack structure: unused fields */
-	stack.fixed_stack_base  = 0;
-	stack.fixed_stack_limit = 0;
+	stack->fixed_stack_base  = 0;
+	stack->fixed_stack_limit = 0;
 
 	/* first we reserve */
-	stack.expandable_stack_bottom = 0;
+	stack->expandable_stack_bottom = 0;
 
 	if ((status = __ntapi->zw_allocate_virtual_memory(
 			params->hprocess,
-			&stack.expandable_stack_bottom,
+			&stack->expandable_stack_bottom,
 			params->stack_zero_bits,
 			&params->stack_size_reserve,
 			NT_MEM_RESERVE,
@@ -112,11 +100,11 @@ int32_t __stdcall __ntapi_tt_create_thread(nt_thread_params * params)
 		return status;
 
 	/* calculate base and limit */
-	base  = stack.expandable_stack_bottom;
+	base  = stack->expandable_stack_bottom;
 	base += params->stack_size_reserve;
 
-	stack.expandable_stack_base   = base;
-	stack.expandable_stack_limit  = base - params->stack_size_commit;
+	stack->expandable_stack_base   = base;
+	stack->expandable_stack_limit  = base - params->stack_size_commit;
 
 	/* guard page */
 	commit             = params->stack_size_commit + __PAGE_SIZE;
@@ -131,7 +119,7 @@ int32_t __stdcall __ntapi_tt_create_thread(nt_thread_params * params)
 			NT_PAGE_READWRITE)))
 		return __create_thread_fail(
 			params->hprocess,
-			stack.expandable_stack_bottom,
+			stack->expandable_stack_bottom,
 			params->stack_size_reserve,
 			status);
 
@@ -146,10 +134,59 @@ int32_t __stdcall __ntapi_tt_create_thread(nt_thread_params * params)
 			&protect_type_old)))
 		return __create_thread_fail(
 			params->hprocess,
-			stack.expandable_stack_bottom,
+			stack->expandable_stack_bottom,
 			params->stack_size_reserve,
 			status);
 
+	/* all done */
+	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;
+
+	/* init */
+	__internals  = __ntapi_internals();
+
+	/* stack */
+	if ((status = __tt_create_thread_stack(params,&stack)))
+		return status;
+
 	/* context */
 	if (params->reg_context) {
 		__ntapi->tt_aligned_block_memcpy(
@@ -162,7 +199,8 @@ int32_t __stdcall __ntapi_tt_create_thread(nt_thread_params * params)
 
 		__INIT_CONTEXT(context);
 		context.INSTRUCTION_POINTER_REGISTER = (uintptr_t)params->start;
-		context.STACK_POINTER_REGISTER       = (uintptr_t)(base) - sizeof(intptr_t);
+		context.STACK_POINTER_REGISTER       = (uintptr_t)(stack.expandable_stack_base)
+		                                        - sizeof(intptr_t);
 	}
 
 
-- 
cgit v1.2.3