Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/ntdll/loader.c | 7 ++++++-
dlls/ntdll/ntdll.spec | 3 ++-
dlls/ntdll/ntdll_misc.h | 2 +-
dlls/ntdll/thread.c | 7 ++++++-
dlls/ntdll/virtual.c | 46 +++++++++++++++++++++++++++++++++++++----
include/winternl.h | 12 ++++++-----
6 files changed, 64 insertions(+), 13 deletions(-)
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 3f422a9c0bee..3d747edaba3b 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -3787,6 +3787,7 @@ void __wine_process_init(void)
ANSI_STRING func_name;
UNICODE_STRING nt_name;
void * (CDECL *init_func)(void);
+ INITIAL_TEB stack;
thread_init();
@@ -3838,11 +3839,15 @@ void __wine_process_init(void)
RemoveEntryList( &wm->ldr.InMemoryOrderModuleList );
InsertHeadList( &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList, &wm->ldr.InMemoryOrderModuleList );
- if ((status = virtual_alloc_thread_stack( NtCurrentTeb(), 0, 0, NULL )) != STATUS_SUCCESS)
+ if ((status = virtual_alloc_thread_stack( &stack, 0, 0, NULL )) != STATUS_SUCCESS)
{
ERR( "Main exe initialization for %s failed, status %x\n",
debugstr_w(wm->ldr.FullDllName.Buffer), status );
NtTerminateProcess( GetCurrentProcess(), status );
}
+ NtCurrentTeb()->Tib.StackBase = stack.StackBase;
+ NtCurrentTeb()->Tib.StackLimit = stack.StackLimit;
+ NtCurrentTeb()->DeallocationStack = stack.DeallocationStack;
+
server_init_process_done();
}
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index aeb9735ba100..e0def228de07 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -526,6 +526,7 @@
@ stdcall RtlCreateUnicodeStringFromAsciiz(ptr str)
@ stdcall RtlCreateUserProcess(ptr long ptr ptr ptr long long long long ptr)
@ stub RtlCreateUserSecurityObject
+@ stdcall RtlCreateUserStack(long long long long long ptr)
@ stdcall RtlCreateUserThread(long ptr long ptr long long ptr ptr ptr ptr)
@ stub RtlCustomCPToUnicodeN
@ stub RtlCutoverTimeToSystemTime
@@ -644,7 +645,7 @@
@ stdcall RtlFreeSid (ptr)
@ stdcall RtlFreeThreadActivationContextStack()
@ stdcall RtlFreeUnicodeString(ptr)
-@ stub RtlFreeUserThreadStack
+@ stdcall RtlFreeUserStack(ptr)
@ stdcall RtlGUIDFromString(ptr ptr)
@ stub RtlGenerate8dot3Name
@ stdcall RtlGetAce(ptr long ptr)
diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
index 3463ebd38adc..d1b895cd364a 100644
--- a/dlls/ntdll/ntdll_misc.h
+++ b/dlls/ntdll/ntdll_misc.h
@@ -173,7 +173,7 @@ extern NTSTATUS virtual_map_section( HANDLE handle, PVOID *addr_ptr, ULONG zero_
pe_image_info_t *image_info ) DECLSPEC_HIDDEN;
extern void virtual_get_system_info( SYSTEM_BASIC_INFORMATION *info ) DECLSPEC_HIDDEN;
extern NTSTATUS virtual_create_builtin_view( void *base ) DECLSPEC_HIDDEN;
-extern NTSTATUS virtual_alloc_thread_stack( TEB *teb, SIZE_T reserve_size,
+extern NTSTATUS virtual_alloc_thread_stack( INITIAL_TEB *stack, SIZE_T reserve_size,
SIZE_T commit_size, SIZE_T *pthread_size ) DECLSPEC_HIDDEN;
extern void virtual_clear_thread_stack( void *stack_end ) DECLSPEC_HIDDEN;
extern BOOL virtual_handle_stack_fault( void *addr ) DECLSPEC_HIDDEN;
diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c
index 46de839400d2..f612d135273f 100644
--- a/dlls/ntdll/thread.c
+++ b/dlls/ntdll/thread.c
@@ -416,6 +416,7 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, SECURITY_DESCRIPTOR *descr,
SIZE_T extra_stack = PTHREAD_STACK_MIN;
data_size_t len = 0;
struct object_attributes *objattr = NULL;
+ INITIAL_TEB stack;
if (process != NtCurrentProcess())
{
@@ -507,9 +508,13 @@ NTSTATUS WINAPI RtlCreateUserThread( HANDLE process, SECURITY_DESCRIPTOR *descr,
info->entry_point = start;
info->entry_arg = param;
- if ((status = virtual_alloc_thread_stack( teb, stack_reserve, stack_commit, &extra_stack )))
+ if ((status = virtual_alloc_thread_stack( &stack, stack_reserve, stack_commit, &extra_stack )))
goto error;
+ teb->Tib.StackBase = stack.StackBase;
+ teb->Tib.StackLimit = stack.StackLimit;
+ teb->DeallocationStack = stack.DeallocationStack;
+
thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch;
thread_data->request_fd = request_pipe[1];
thread_data->reply_fd = -1;
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index 78973a8cda43..a3ea195c917b 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -1924,7 +1924,7 @@ NTSTATUS virtual_create_builtin_view( void *module )
/***********************************************************************
* virtual_alloc_thread_stack
*/
-NTSTATUS virtual_alloc_thread_stack( TEB *teb, SIZE_T reserve_size, SIZE_T commit_size, SIZE_T *pthread_size )
+NTSTATUS virtual_alloc_thread_stack( INITIAL_TEB *stack, SIZE_T reserve_size, SIZE_T commit_size, SIZE_T *pthread_size )
{
struct file_view *view;
NTSTATUS status;
@@ -1978,9 +1978,11 @@ NTSTATUS virtual_alloc_thread_stack( TEB *teb, SIZE_T reserve_size, SIZE_T commi
}
/* note: limit is lower than base since the stack grows down */
- teb->DeallocationStack = view->base;
- teb->Tib.StackBase = (char *)view->base + view->size;
- teb->Tib.StackLimit = (char *)view->base + 2 * page_size;
+ stack->OldStackBase = 0;
+ stack->OldStackLimit = 0;
+ stack->DeallocationStack = view->base;
+ stack->StackBase = (char *)view->base + view->size;
+ stack->StackLimit = (char *)view->base + 2 * page_size;
done:
server_leave_uninterrupted_section( &csVirtual, &sigset );
return status;
@@ -2001,6 +2003,42 @@ void virtual_clear_thread_stack( void *stack_end )
if (force_exec_prot) mprotect( stack, size, PROT_READ | PROT_WRITE | PROT_EXEC );
}
+/**********************************************************************
+ * RtlCreateUserStack (NTDLL.@)
+ */
+NTSTATUS WINAPI RtlCreateUserStack( SIZE_T commit, SIZE_T reserve, ULONG zero_bits,
+ SIZE_T commit_align, SIZE_T reserve_align, INITIAL_TEB *stack )
+{
+ TRACE("commit %#lx, reserve %#lx, zero_bits %u, commit_align %#lx, reserve_align %#lx, stack %p\n",
+ commit, reserve, zero_bits, commit_align, reserve_align, stack);
+
+ if (!commit_align || !reserve_align)
+ return STATUS_INVALID_PARAMETER;
+
+ if (!commit || !reserve)
+ {
+ IMAGE_NT_HEADERS *nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress );
+ if (!reserve) reserve = nt->OptionalHeader.SizeOfStackReserve;
+ if (!commit) commit = nt->OptionalHeader.SizeOfStackCommit;
+ }
+
+ reserve = (reserve + reserve_align - 1) & ~(reserve_align - 1);
+ commit = (commit + commit_align - 1) & ~(commit_align - 1);
+
+ return virtual_alloc_thread_stack( stack, reserve, commit, NULL );
+}
+
+/**********************************************************************
+ * RtlFreeUserStack (NTDLL.@)
+ */
+void WINAPI RtlFreeUserStack( void *stack )
+{
+ SIZE_T size = 0;
+
+ TRACE("stack %p\n", stack);
+
+ NtFreeVirtualMemory( NtCurrentProcess(), &stack, &size, MEM_RELEASE );
+}
/***********************************************************************
* virtual_handle_fault
diff --git a/include/winternl.h b/include/winternl.h
index e7f89b005922..b87aa2298c6b 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -2104,11 +2104,11 @@ typedef struct _DIRECTORY_BASIC_INFORMATION {
} DIRECTORY_BASIC_INFORMATION, *PDIRECTORY_BASIC_INFORMATION;
typedef struct _INITIAL_TEB {
- PVOID StackBase;
- PVOID StackLimit;
- PVOID StackCommit;
- PVOID StackCommitMax;
- PVOID StackReserved;
+ void *OldStackBase;
+ void *OldStackLimit;
+ void *StackBase;
+ void *StackLimit;
+ void *DeallocationStack;
} INITIAL_TEB, *PINITIAL_TEB;
typedef enum _PORT_INFORMATION_CLASS {
@@ -2618,6 +2618,7 @@ NTSYSAPI BOOLEAN WINAPI RtlCreateUnicodeString(PUNICODE_STRING,LPCWSTR);
NTSYSAPI BOOLEAN WINAPI RtlCreateUnicodeStringFromAsciiz(PUNICODE_STRING,LPCSTR);
NTSYSAPI NTSTATUS WINAPI RtlCreateUserProcess(UNICODE_STRING*,ULONG,RTL_USER_PROCESS_PARAMETERS*,SECURITY_DESCRIPTOR*,SECURITY_DESCRIPTOR*,HANDLE,BOOLEAN,HANDLE,HANDLE,RTL_USER_PROCESS_INFORMATION*);
NTSYSAPI NTSTATUS WINAPI RtlCreateUserThread(HANDLE,SECURITY_DESCRIPTOR*,BOOLEAN,PVOID,SIZE_T,SIZE_T,PRTL_THREAD_START_ROUTINE,void*,HANDLE*,CLIENT_ID*);
+NTSYSAPI NTSTATUS WINAPI RtlCreateUserStack(SIZE_T,SIZE_T,ULONG,SIZE_T,SIZE_T,INITIAL_TEB*);
NTSYSAPI void WINAPI RtlDeactivateActivationContext(DWORD,ULONG_PTR);
NTSYSAPI PVOID WINAPI RtlDecodePointer(PVOID);
NTSYSAPI NTSTATUS WINAPI RtlDecompressBuffer(USHORT,PUCHAR,ULONG,PUCHAR,ULONG,PULONG);
@@ -2691,6 +2692,7 @@ NTSYSAPI void WINAPI RtlFreeOemString(POEM_STRING);
NTSYSAPI DWORD WINAPI RtlFreeSid(PSID);
NTSYSAPI void WINAPI RtlFreeThreadActivationContextStack(void);
NTSYSAPI void WINAPI RtlFreeUnicodeString(PUNICODE_STRING);
+NTSYSAPI void WINAPI RtlFreeUserStack(void*);
NTSYSAPI NTSTATUS WINAPI RtlGetAce(PACL,DWORD,LPVOID *);
NTSYSAPI NTSTATUS WINAPI RtlGetActiveActivationContext(HANDLE*);
NTSYSAPI NTSTATUS WINAPI RtlGetCompressionWorkSpaceSize(USHORT,PULONG,PULONG);
--
2.20.1