Signed-off-by: Zebediah Figura zfigura@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);